diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..8306744 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 30baaa6..f224979 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,13 +31,5 @@ androidExtensions { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':main') - implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} -repositories { - mavenCentral() -} +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index f1b4245..e90531f 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -19,3 +19,6 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile +-libraryjars libs/litepal-1.5.1.jar +-dontwarn org.litepal.** +-keep class org.litepal.** {*; } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4bbc123..7944f1c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,30 +3,59 @@ package="com.example.quxiang"> - + + + + - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/quxiang/opensource/MainActivity.java b/app/src/main/java/com/example/quxiang/opensource/MainActivity.java deleted file mode 100644 index 07eb8d7..0000000 --- a/app/src/main/java/com/example/quxiang/opensource/MainActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.example.quxiang.opensource; - -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; - -import com.example.quxiang.R; - -public class MainActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - } -} diff --git a/app/src/main/java/com/example/quxiang/opensource/OpenSourceLoginActivity.kt b/app/src/main/java/com/example/quxiang/opensource/OpenSourceLoginActivity.kt new file mode 100644 index 0000000..59f64c9 --- /dev/null +++ b/app/src/main/java/com/example/quxiang/opensource/OpenSourceLoginActivity.kt @@ -0,0 +1,225 @@ +package com.example.quxiang.opensource + +import android.content.Context +import android.os.Bundle +import android.os.CountDownTimer +import android.support.transition.Fade +import android.support.transition.TransitionManager +import android.transition.Transition +import android.view.View +import android.view.inputmethod.InputMethodManager +import com.example.core.extension.logWarn +import com.example.core.extension.showToast +import com.example.core.util.AndroidVersion +import com.example.core.util.GlobalUtil +import com.example.main.common.callback.SimpleTransitionListener +import com.example.main.event.FinishActivityEvent +import com.example.main.login.ui.LoginActivity +import com.example.main.util.ResponseHandler +import com.example.quxiang.R +import com.quxianggif.network.model.Callback +import com.quxianggif.network.model.FetchVCode +import com.quxianggif.network.model.PhoneLogin +import com.quxianggif.network.model.Response +import com.quxianggif.network.request.FetchVCodeRequest +import kotlinx.android.synthetic.main.activity_login.* +import org.greenrobot.eventbus.EventBus +import java.lang.Exception +import java.util.* +import java.util.regex.Pattern + +/** + * Anthor: Zhuangmingzhu + * Date: 2019/4/22 下午5:55 + * Describe:开源版界面登录,支持手机号登录,如果登陆的账号没有注册就会跳转到注册界面如果已经注册过了就直接会跳转到主界面 + */ +class OpenSourceLoginActivity :LoginActivity(){ + + companion object { + const val TAG="OpenSourceLoginActivity" + } + + private lateinit var timer:CountDownTimer + + //是否正在登录中 + private var isLogin=false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_login) + } + + override fun setupViews() { + super.setupViews() + val isStartWithTransition=intent.getBooleanExtra(LoginActivity.START_WITH_TRANSITION,false) + if(AndroidVersion.hasLollipop()&&isStartWithTransition){ + isTransitioning=true + window.sharedElementEnterTransition.addListener(object : SimpleTransitionListener() { + override fun onTransitionEnd(transition: Transition?) { + val event=FinishActivityEvent() + event.activityClass=OpenSourceSplashActivity::class.java + EventBus.getDefault().post(event) + isTransitioning=false + fadeElementsIn() + } + }) + }else{ + loginLayoutBottom.visibility= View.VISIBLE + loginBgWallLayout.visibility=View.VISIBLE + } + + timer=SMSTimer(60*1000,1000) + getVerifyCode.setOnClickListener { + getVerifyCodeAction() + } + + loginButton.setOnClickListener { + getLoginAction() + } + + } + + //获取验证码 + private fun getVerifyCodeAction(){ + val number=phoneNumberEdit.text.toString() + if(number.isEmpty()){ + showToast(GlobalUtil.getString(R.string.phone_number_is_empty)) + return + } + + if(!isLegalPhone(number)){ + return + } + + getVerifyCode.isClickable=false + processGetVerifyCode(number) + } + + //登录操作 + private fun getLoginAction(){ + if(isLogin) return + val number=phoneNumberEdit.text.toString() + val code=verifyCodeEdit.text.toString() + if(number.isEmpty()||code.isEmpty()){ + showToast(GlobalUtil.getString(R.string.phone_number_or_code_is_empty)) + return + } + + if(!isLegalPhone(number)){ + return + } + processLogin(number,code) + } + + //验证手机号是否合法 + private fun isLegalPhone(number:String):Boolean{ + val pattern="^1\\d{10}\$" + if(!Pattern.matches(pattern,number)){ + showToast(GlobalUtil.getString(R.string.phone_number_is_invalid)) + return false + } + return true + } + + //将LoginActivity的界面元素使用淡入的方式显示出来 + private fun fadeElementsIn(){ + TransitionManager.beginDelayedTransition(loginLayoutBottom, Fade()) + loginLayoutBottom.visibility = View.VISIBLE + TransitionManager.beginDelayedTransition(loginBgWallLayout,Fade()) + loginBgWallLayout.visibility = View.VISIBLE + } + + //开始获取验证码 + private fun processGetVerifyCode(number: String){ + FetchVCode.getResponse(number,object :Callback{ + override fun onResponse(response: Response) { + if(response.status==0){ + timer.start() + verifyCodeEdit.requestFocus() + }else{ + showToast(response.msg) + getVerifyCode.isClickable=true + } + } + + override fun onFailure(e: Exception) { + logWarn(TAG,e.message,e) + ResponseHandler.handleFailure(e) + getVerifyCode.isClickable=true + } + + }) + } + + //开始登陆 + private fun processLogin(number: String,code:String){ + hideSoftKeyboard() + loginInProgress(true) + PhoneLogin.getResponse(number,code,object:Callback{ + override fun onResponse(response: Response) { + if(!ResponseHandler.handleResponse(response)){ + val thirdPartyLogin=response as PhoneLogin + val status=thirdPartyLogin.status + val msg=thirdPartyLogin.msg + val userId=thirdPartyLogin.userId + val token=thirdPartyLogin.token + when (status){ + 0->{ + hideSoftKeyboard() + //处理登录成功时的逻辑,包括数据缓存,界面跳转等 + saveAuthData(userId,token, TYPE_PHONE_LOGIN) + getUserBaseInfo() + } + 10101->{ + hideSoftKeyboard() + OpenSourceRegisterActivity.registerByPhone(this@OpenSourceLoginActivity,number,code) + loginInProgress(false) + } + else->{ + logWarn(TAG, "Login failed. " + GlobalUtil.getResponseClue(status, msg)) + showToast(response.msg) + loginInProgress(false) + } + } + }else{ + loginInProgress(false) + } + } + + override fun onFailure(e: Exception) { + logWarn(TAG, e.message, e) + ResponseHandler.handleFailure(e) + loginInProgress(false) + } + + }) + } + + //根据用户是否正在注册来刷新页面。如果正在处理就显示进度条,否则的话就显示输入框 + private fun loginInProgress(inProgress:Boolean){ + if(AndroidVersion.hasMarshmallow()&&!(inProgress&&loginRootLayout.keyboardShowed)){ + TransitionManager.beginDelayedTransition(loginRootLayout,Fade()) + } + isLogin=inProgress + if (inProgress) { + loginInputElements.visibility = View.INVISIBLE + loginProgressBar.visibility = View.VISIBLE + } else { + loginProgressBar.visibility = View.INVISIBLE + loginInputElements.visibility = View.VISIBLE + } + } + + inner class SMSTimer(millisInFuture:Long,countDownInterval:Long):CountDownTimer(millisInFuture,countDownInterval){ + + override fun onFinish() { + getVerifyCode.text="获取验证码" + getVerifyCode.isClickable=true + } + + override fun onTick(millisUntilFinished: Long) { + getVerifyCode.text=String.format(GlobalUtil.getString(R.string.sms_is_sent),millisUntilFinished/1000) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/quxiang/opensource/OpenSourceRegisterActivity.kt b/app/src/main/java/com/example/quxiang/opensource/OpenSourceRegisterActivity.kt new file mode 100644 index 0000000..4331ba8 --- /dev/null +++ b/app/src/main/java/com/example/quxiang/opensource/OpenSourceRegisterActivity.kt @@ -0,0 +1,126 @@ +package com.example.quxiang.opensource + +import android.app.Activity +import android.content.Intent +import android.view.KeyEvent +import android.widget.TextView +import com.example.core.extension.logDebug +import com.example.core.extension.logWarn +import com.example.core.extension.showToast +import com.example.core.util.GlobalUtil +import com.example.main.login.ui.RegisterActivity +import com.example.main.util.ResponseHandler +import com.example.quxiang.R +import com.quxianggif.network.model.BaseRegister +import com.quxianggif.network.model.Callback +import com.quxianggif.network.model.PhoneRegister +import com.quxianggif.network.model.Response +import java.lang.Exception + +/** + * Anthor: Zhuangmingzhu + * Date: 2019/4/24 下午4:05 + * Describe:当登录账号不存在是,跳转到注册界面来进行账号注册 + */ +class OpenSourceRegisterActivity :RegisterActivity(),TextView.OnEditorActionListener{ + + private var number="" + + private var code="" + + //获取Intent中传递过来的数据并显示到界面上 + override fun setupViews() { + super.setupViews() + if(intent.getStringExtra(INTENT_PHONE_NUMBER)==null||intent.getStringExtra(INTENT_VERIFY_CODE) == null){ + showToast(GlobalUtil.getString(R.string.phone_number_verify_code_is_null)) + finish() + return + } + number=intent.getStringExtra(INTENT_PHONE_NUMBER) + code=intent.getStringExtra(INTENT_VERIFY_CODE) + nicknameEditText.requestFocus() + } + + //开始执行注册逻辑 + override fun doRegister() { + if(isRegistering) return + when(loginType){ + TYPE_PHONE_LOGIN->processPhoneRegister() + } + } + + //注册手机号登录账号 + private fun processPhoneRegister(){ + if(isNicknameValid){ + hideSoftKeyboard() + nicknameLayout.isErrorEnabled=false + registerInProgress(true) + sendPhoneRegisterRequest() + } + } + + private fun sendPhoneRegisterRequest(){ + PhoneRegister.getResponse(number,code,nicknameEditText.text.toString().trim(),object :Callback{ + override fun onResponse(response: Response) { + handleRegisterCallback(response) + } + + override fun onFailure(e: Exception) { + logWarn(TAG, e.message, e) + registerInProgress(false) + ResponseHandler.handleFailure(e) + } + + }) + } + + private fun handleRegisterCallback(response: Response){ + if(activity==null){ + return + } + if(!ResponseHandler.handleResponse(response)){ + val register=response as BaseRegister + val status=register.status + when(status){ + 0-> { + logDebug(TAG, "token is " + register.token + " , getAvatar is " + register.avatar) + val userId = register.userId + val token=register.token + saveAuthData(userId.toLong(),token,loginType) + registerSuccess() + } + 10105->{ + registerInProgress(false) + nicknameLayout.isErrorEnabled=true + nicknameLayout.error=GlobalUtil.getString(R.string.register_failed_nickname_is_used) + } + else->{ + logWarn(TAG, "Register failed. " + GlobalUtil.getResponseClue(status, register.msg)) + showToast(register.msg) + finish() + } + } + }else{ + finish() + } + } + + //处理注册成功时的逻辑,包括数据缓存,界面跳转等 + private fun registerSuccess(){ + getUserBaseInfo() + } + + companion object{ + + private const val TAG="OpenSourceRegisterActivity" + + fun registerByPhone(activity:Activity,number:String,code:String){ + val intent= Intent(activity,OpenSourceRegisterActivity::class.java) + intent.putExtra(INTENT_PHONE_NUMBER,number) + intent.putExtra(INTENT_VERIFY_CODE, code) + intent.putExtra(INTENT_LOGIN_TYPE, TYPE_PHONE_LOGIN) + activity.startActivity(intent) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/quxiang/opensource/OpenSourceSplashActivity.kt b/app/src/main/java/com/example/quxiang/opensource/OpenSourceSplashActivity.kt new file mode 100644 index 0000000..439d75b --- /dev/null +++ b/app/src/main/java/com/example/quxiang/opensource/OpenSourceSplashActivity.kt @@ -0,0 +1,19 @@ +package com.example.quxiang.opensource + +import android.os.Bundle +import com.example.main.init.ui.SplashActivity +import com.example.quxiang.R +import kotlinx.android.synthetic.main.activity_splash.* + +/** + * Anthor: Zhuangmingzhu + * Date: 2019/4/2 下午7:05 + * Describe:开源版闪屏Activity界面 + */ +class OpenSourceSplashActivity:SplashActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_splash) + logoView=logo + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/quxiang/opensource/OpensourceSplashActivity.kt b/app/src/main/java/com/example/quxiang/opensource/OpensourceSplashActivity.kt deleted file mode 100644 index e9723de..0000000 --- a/app/src/main/java/com/example/quxiang/opensource/OpensourceSplashActivity.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.example.quxiang.opensource - -/** - * Anthor: Zhuangmingzhu - * Date: 2019/4/2 下午7:05 - * Describe:开源版闪屏Activity界面 - */ -class OpensourceSplashActivity { -} \ No newline at end of file diff --git a/app/src/main/java/com/example/quxiang/opensource/view/LoginLayout.kt b/app/src/main/java/com/example/quxiang/opensource/view/LoginLayout.kt new file mode 100644 index 0000000..52b3e13 --- /dev/null +++ b/app/src/main/java/com/example/quxiang/opensource/view/LoginLayout.kt @@ -0,0 +1,45 @@ +package com.example.quxiang.opensource.view + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import kotlinx.android.synthetic.main.activity_login.view.* + +/** + * Anthor: Zhuangmingzhu + * Date: 2019/4/23 下午7:00 + * Describe:自定义登录界面Layout,监听布局高度的变化,如果高宽比小于4:3说明此键盘弹出,应改变布局的比列结果以保证所有元素都不会被键盘遮挡 + */ +class LoginLayout(context: Context,attributes:AttributeSet):LinearLayout(context,attributes) { + + var keyboardShowed=false + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + if(changed){ + val width=right-left + val height=bottom-top + if(height.toFloat()/width.toFloat()<4f/3f){//如果高宽比小于4:3说明此事键盘弹出 + post { + loginBgWallLayout.visibility= View.INVISIBLE + val params=loginLayoutTop.layoutParams as LayoutParams + params.weight=1.5f + keyboardShowed=true + loginLayoutTop.requestLayout() + } + }else{ + if(keyboardShowed){ + post { + loginBgWallLayout.visibility=View.VISIBLE + val params=loginLayoutTop.layoutParams as LayoutParams + params.weight=6f + loginLayoutTop.requestLayout() + } + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/follow_button.png b/app/src/main/res/drawable-xxhdpi/follow_button.png new file mode 100644 index 0000000..ce451a2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/follow_button.png differ diff --git a/app/src/main/res/drawable-xxhdpi/follow_button_pressed.png b/app/src/main/res/drawable-xxhdpi/follow_button_pressed.png new file mode 100644 index 0000000..5ea164c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/follow_button_pressed.png differ diff --git a/app/src/main/res/drawable-xxhdpi/logo_reverse.png b/app/src/main/res/drawable-xxhdpi/logo_reverse.png new file mode 100755 index 0000000..6ddccce Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/logo_reverse.png differ diff --git a/app/src/main/res/drawable-xxhdpi/phone_login_button.png b/app/src/main/res/drawable-xxhdpi/phone_login_button.png new file mode 100755 index 0000000..795e9e5 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/phone_login_button.png differ diff --git a/app/src/main/res/drawable-xxhdpi/phone_login_button_pressed.png b/app/src/main/res/drawable-xxhdpi/phone_login_button_pressed.png new file mode 100755 index 0000000..e56d069 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/phone_login_button_pressed.png differ diff --git a/app/src/main/res/drawable-xxhdpi/user_home_page_bg.png b/app/src/main/res/drawable-xxhdpi/user_home_page_bg.png new file mode 100644 index 0000000..71bf883 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/user_home_page_bg.png differ diff --git a/app/src/main/res/drawable/phone_login_button_bg.xml b/app/src/main/res/drawable/phone_login_button_bg.xml new file mode 100644 index 0000000..398dedc --- /dev/null +++ b/app/src/main/res/drawable/phone_login_button_bg.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f3a9453 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +