From 0c89bf11bcddd39b5193bb19e28399648c59a2b8 Mon Sep 17 00:00:00 2001
From: nilupeng <qingingrunt2010@qq.com>
Date: Sat, 29 Jan 2022 11:04:25 +0000
Subject: [PATCH] 登录界面及接口
---
app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java | 129 +++
app/src/main/java/com/runt/open/mvvm/MyApplication.java | 11
app/src/main/res/values/styles.xml | 44 +
app/src/main/res/values/themes.xml | 5
app/src/main/java/com/runt/open/mvvm/retrofit/api/LoginApiCenter.java | 49 +
app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java | 1
app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java | 159 +++
app/src/main/java/com/runt/open/mvvm/util/PhoneUtil.java | 77 +
app/src/main/java/com/runt/open/mvvm/listener/CrashHandler.java | 260 ++++++
app/src/main/java/com/runt/open/mvvm/ui/login/CodeTimer.java | 40 +
app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java | 132 +++
app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java | 2
app/src/main/java/com/runt/open/mvvm/util/PreferencesUtils.java | 352 ++++++++
app/src/main/res/values/strings.xml | 67 +
app/src/main/java/com/runt/open/mvvm/MainActivity.java | 16
app/src/main/AndroidManifest.xml | 2
app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java | 7
app/src/main/res/color/btn_txt_normal.xml | 9
/dev/null | 48 -
app/src/main/java/com/runt/open/mvvm/config/Configuration.java | 16
app/src/main/res/layout/activity_login.xml | 138 +++
app/src/main/res/layout/activity_web.xml | 40 +
app/src/main/java/com/runt/open/mvvm/data/Results.java | 16
app/src/main/java/com/runt/open/mvvm/util/MyAnimations.java | 477 +++++++++++
app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java | 287 +++++++
25 files changed, 2,322 insertions(+), 62 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1b81d3c..4e8fded 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -51,6 +51,8 @@
<action android:name="com.zfwl.merchant.activities.MainActivity" />
</intent-filter>
</activity>
+ <activity android:name=".ui.login.RegisterLoginActivity" />
+ <activity android:name=".ui.web.WebViewActivity" />
</application>
</manifest>
\ No newline at end of file
diff --git a/app/src/main/java/com/runt/open/mvvm/MainActivity.java b/app/src/main/java/com/runt/open/mvvm/MainActivity.java
index 6871cf3..1297088 100644
--- a/app/src/main/java/com/runt/open/mvvm/MainActivity.java
+++ b/app/src/main/java/com/runt/open/mvvm/MainActivity.java
@@ -1,7 +1,12 @@
package com.runt.open.mvvm;
import android.Manifest;
+import android.content.Intent;
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultCallback;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;
@@ -11,6 +16,7 @@
import com.runt.open.mvvm.data.PhoneDevice;
import com.runt.open.mvvm.databinding.ActivityMainBinding;
import com.runt.open.mvvm.listener.ResPonse;
+import com.runt.open.mvvm.ui.login.RegisterLoginActivity;
import com.runt.open.mvvm.ui.main.MainViewModel;
public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> {
@@ -20,6 +26,16 @@
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupWithNavController(binding.navView, navController);
checkPermission();
+ ActivityResultLauncher<Intent> launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
+ @Override
+ public void onActivityResult(ActivityResult result) {
+ if(result.getResultCode() == RESULT_CODE_SUCESS){
+ showToast("登录成功");
+ }
+ }
+ });
+ Intent intent = new Intent(mContext, RegisterLoginActivity.class);
+ launcher.launch(intent);
}
private void showPermissionDialog(){
diff --git a/app/src/main/java/com/runt/open/mvvm/MyApplication.java b/app/src/main/java/com/runt/open/mvvm/MyApplication.java
index ab1a97f..30f98b9 100644
--- a/app/src/main/java/com/runt/open/mvvm/MyApplication.java
+++ b/app/src/main/java/com/runt/open/mvvm/MyApplication.java
@@ -11,6 +11,7 @@
import com.bytedance.sdk.openadsdk.TTAdConfig;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdSdk;
+import com.runt.open.mvvm.listener.CrashHandler;
import com.runt.open.mvvm.util.MyLog;
import com.scwang.smart.refresh.footer.ClassicsFooter;
import com.scwang.smart.refresh.header.ClassicsHeader;
@@ -137,6 +138,16 @@
MyLog.e(TAG,"TTAdSdk fail");
}
});
+ CrashHandler crashHandler = CrashHandler.getInstance();
+ crashHandler.init(getApplicationContext(), new CrashHandler.CrashListener() {
+ @Override
+ public void onCrash() {
+ for(Activity activity : activities){
+ activity.finish();
+ }
+ System.exit(0);
+ }
+ });
}
/**
diff --git a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java
index 5d775df..1629d1c 100644
--- a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java
+++ b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java
@@ -28,10 +28,12 @@
import com.runt.open.mvvm.base.model.BaseViewModel;
import com.runt.open.mvvm.base.model.ViewModelFactory;
import com.runt.open.mvvm.listener.ResPonse;
+import com.runt.open.mvvm.util.PreferencesUtils;
import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
+import java.util.Set;
import dmax.dialog.SpotsDialog;
@@ -48,6 +50,9 @@
public final String[] LOCATION_PERMISSIONS = new String []{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION};
public final String[] CAMERA_PERMISSIONS = new String[]{ FILE_PERMISSIONS[0],FILE_PERMISSIONS[1], Manifest.permission.CAMERA};
public final String[] CAMERA_RECORD_PERMISSIONS = new String[]{ FILE_PERMISSIONS[0],FILE_PERMISSIONS[1], Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO};
+
+ public static final String PARAMS_TITLE = "title";
+ public static final String PARAMS_URL = "url";
public static final int RESULT_LOGIN = 100,RESULT_LOGIN_RECREATE = 103,RESULT_BIND = 101,RESULT_SENDEDFILES = 105,RESULT_DISSCONNECT = 104,
RESULT_UPDATEUSER = 115,RESULT_LOGOUT = 113, REQUEST_CODE_ACTIVITY = 333;
@@ -366,4 +371,128 @@
return false;
}
+
+ public boolean getBooleanUserPrefrence(String key){
+ return PreferencesUtils.getBoolean(this,key,false,PreferencesUtils.USER);
+ }
+
+ public boolean getBooleanProjectPrefrence(String key){
+ return PreferencesUtils.getBoolean(this,key,false,PreferencesUtils.PROJECT);
+ }
+
+ public String getStringUserPrefrence(String key){
+ return PreferencesUtils.getString(this,key,"",PreferencesUtils.USER);
+ }
+
+ public String getStringProjectPrefrence(String key){
+ return PreferencesUtils.getString(this,key,"",PreferencesUtils.PROJECT);
+ }
+
+ public Integer getIntProjectPrefrence(String key){
+ return PreferencesUtils.getInt(this,key,0,PreferencesUtils.PROJECT);
+ }
+
+ public Long getLongProjectPrefrence(String key){
+ return PreferencesUtils.getLong(this,key,0,PreferencesUtils.PROJECT);
+ }
+
+ public float getFloatProjectPrefrence(String key){
+ return PreferencesUtils.getFloat(this,key,0,PreferencesUtils.PROJECT);
+ }
+
+ public Set getStringSetProjectPrefrence(String key){
+ return PreferencesUtils.getStringSet(this,key,PreferencesUtils.PROJECT);
+ }
+
+ public Integer getIntUserPrefrence(String key){
+ return PreferencesUtils.getInt(this,key,0,PreferencesUtils.USER);
+ }
+
+ public Long getLongUserPrefrence(String key){
+ return PreferencesUtils.getLong(this,key,0,PreferencesUtils.USER);
+ }
+
+ public float getFloatUserPrefrence(String key){
+ return PreferencesUtils.getFloat(this,key,0,PreferencesUtils.USER);
+ }
+
+ public Set getStringSetUserPrefrence(String key){
+ return PreferencesUtils.getStringSet(this,key,PreferencesUtils.USER);
+ }
+
+
+ public void putBooleanUserPrefrence(String key ,Boolean value){
+ PreferencesUtils.putBoolean(this,key,value,PreferencesUtils.USER);
+ }
+
+ public void putBooleanProjectPrefrence(String key,Boolean value){
+ PreferencesUtils.putBoolean(this,key,value,PreferencesUtils.PROJECT);
+ }
+
+ public void putStringUserPrefrence(String key,String value){
+ PreferencesUtils.putString(this,key,value,PreferencesUtils.USER);
+ }
+
+ public void putStringProjectPrefrence(String key,String value){
+ PreferencesUtils.putString(this,key,value,PreferencesUtils.PROJECT);
+ }
+
+ public void putIntProjectPrefrence(String key,int value){
+ PreferencesUtils.putInt(this,key,value,PreferencesUtils.PROJECT);
+ }
+
+ public void putLongProjectPrefrence(String key,long value){
+ PreferencesUtils.putLong(this,key,value,PreferencesUtils.PROJECT);
+ }
+
+ public void putFloatProjectPrefrence(String key,float value){
+ PreferencesUtils.putFloat(this,key,value,PreferencesUtils.PROJECT);
+ }
+
+ public void putStringSetProjectPrefrence(String key, Set value){
+ PreferencesUtils.putStringSet(this,key,value,PreferencesUtils.PROJECT);
+ }
+
+ public void putIntUserPrefrence(String key,int value){
+ PreferencesUtils.putInt(this,key,value,PreferencesUtils.USER);
+ }
+
+ public void putLongUserPrefrence(String key,long value){
+ PreferencesUtils.putLong(this,key,value,PreferencesUtils.USER);
+ }
+
+ public void putFloatUserPrefrence(String key,float value){
+ PreferencesUtils.putFloat(this,key,value,PreferencesUtils.USER);
+ }
+
+ public void putStringSetUserPrefrence(String key, Set value){
+ PreferencesUtils.putStringSet(this,key,value,PreferencesUtils.USER);
+ }
+
+
+ public void removeUserKey(String key){
+ PreferencesUtils.removeKey(this,key,PreferencesUtils.USER);
+ }
+
+ public void removeProjectKey(String key){
+ PreferencesUtils.removeKey(this,key,PreferencesUtils.PROJECT);
+ }
+
+ public void removeUserValue(String Value){
+ PreferencesUtils.removeValue(this,Value,PreferencesUtils.USER);
+ }
+
+ public void removeProjectValue(String Value){
+ PreferencesUtils.removeValue(this,Value,PreferencesUtils.PROJECT);
+ }
+
+
+ public void clearProjectData(){
+ PreferencesUtils.clearData(this,PreferencesUtils.PROJECT);
+ }
+ public void clearUserData(){
+ PreferencesUtils.clearData(this,PreferencesUtils.USER);
+ }
+
+
}
diff --git a/app/src/main/java/com/runt/open/mvvm/config/Configuration.java b/app/src/main/java/com/runt/open/mvvm/config/Configuration.java
new file mode 100644
index 0000000..e865ba8
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/config/Configuration.java
@@ -0,0 +1,16 @@
+package com.runt.open.mvvm.config;
+
+/**
+ * My father is Object, ites purpose of
+ *
+ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/1/29.
+ */
+public class Configuration {
+
+ public final static String KEY_CODE= "code";
+ public static final String KEY_TOKEN = "token";
+ public static final String KEY_USERNAME = "username";
+ public static final String KEY_PHONE = "phone";
+ public static final String KEY_USERPASS = "userpass";
+ public final static String IS_LOGIN= "is_login";
+}
diff --git a/app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java b/app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java
index 9b758bf..8ddd410 100644
--- a/app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java
+++ b/app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java
@@ -6,6 +6,7 @@
* Created by Administrator on 2021/10/28 0028.
*/
public class BaseApiResult<D extends Object> implements Serializable {
+
public String msg;
public int code = 200;
public D data;
diff --git a/app/src/main/java/com/runt/open/mvvm/data/Results.java b/app/src/main/java/com/runt/open/mvvm/data/Results.java
new file mode 100644
index 0000000..fc55568
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/data/Results.java
@@ -0,0 +1,16 @@
+package com.runt.open.mvvm.data;
+
+import com.runt.open.mvvm.ui.login.UserBean;
+
+/**
+ * My father is Object, ites purpose of
+ *
+ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/1/29.
+ */
+public class Results {
+
+ public static class LoggedInUser extends BaseApiResult<UserBean> { }
+
+ public static class StringApiResult extends BaseApiResult<String>{ }
+
+}
diff --git a/app/src/main/java/com/runt/open/mvvm/listener/CrashHandler.java b/app/src/main/java/com/runt/open/mvvm/listener/CrashHandler.java
new file mode 100644
index 0000000..a837be7
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/listener/CrashHandler.java
@@ -0,0 +1,260 @@
+package com.runt.open.mvvm.listener;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Environment;
+import android.os.Looper;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * My father is Object, ites purpose of 崩溃监听
+ *
+ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2021-4-13.
+ */
+
+public class CrashHandler implements Thread.UncaughtExceptionHandler {
+
+ public static final String TAG = "CrashHandler";
+
+ //系统默认的UncaughtException处理类
+ private Thread.UncaughtExceptionHandler mDefaultHandler;
+
+ CrashListener crashListener;
+
+ //CrashHandler实例
+ private static CrashHandler instance;
+ //程序的Context对象
+ private Context mContext;
+ //用来存储设备信息和异常信息
+ private Map<String, String> infos = new HashMap<String, String>();
+
+ //用于格式化日期,作为日志文件名的一部分
+ private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ /** 保证只有一个CrashHandler实例 */
+ private CrashHandler() {}
+
+ /** 获取CrashHandler实例 ,单例模式 */
+ public static CrashHandler getInstance() {
+ Log.i(TAG, "getInstance");
+ if(instance == null)
+ instance = new CrashHandler();
+ return instance;
+ }
+
+ /**
+ * 初始化
+ */
+ public void init(Context context) {
+ Log.i(TAG, "init context:"+context);
+ mContext = context;
+ //获取系统默认的UncaughtException处理器
+ mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+ //设置该CrashHandler为程序的默认处理器
+ Thread.setDefaultUncaughtExceptionHandler(this);
+ }
+
+ /**
+ * 初始化
+ */
+ public void init(Context context,CrashListener crashListener) {
+ Log.i(TAG, "init context:"+context);
+ mContext = context;
+ this.crashListener = crashListener;
+ //设置该CrashHandler为程序的默认处理器
+ Thread.setDefaultUncaughtExceptionHandler(this);
+ }
+
+ /**
+ * 当UncaughtException发生时会转入该函数来处理
+ */
+ @Override
+ public void uncaughtException(Thread thread, Throwable ex) {
+ Log.i(TAG, "uncaughtException Throwable:"+ex);
+ if (!handleException(ex) && mDefaultHandler != null) {
+ //如果用户没有处理则让系统默认的异常处理器来处理
+ mDefaultHandler.uncaughtException(thread, ex);
+ } else if(crashListener != null){
+ crashListener.onCrash();
+ } else {
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "error : ", e);
+ }
+ //退出程序
+ android.os.Process.killProcess(android.os.Process.myPid());
+ System.exit(1);
+ }
+ }
+
+ /**
+ * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
+ *
+ * @param ex
+ * @return true:如果处理了该异常信息;否则返回false.
+ */
+ private boolean handleException(Throwable ex) {
+ Log.i(TAG, "handleException Throwable:"+ex);
+ if (ex == null) {
+ return false;
+ }
+ //收集设备参数信息
+ collectDeviceInfo(mContext);
+
+ //使用Toast来显示异常信息
+ new Thread() {
+ @Override
+ public void run() {
+ Looper.prepare();
+ Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ }.start();
+ //保存日志文件
+ saveCatchInfo2File(ex);
+ return true;
+ }
+
+ /**
+ * 收集设备参数信息
+ * @param ctx
+ */
+ public void collectDeviceInfo(Context ctx) {
+ Log.i(TAG, "collectDeviceInfo Context:"+ctx);
+ try {
+ PackageManager pm = ctx.getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
+ if (pi != null) {
+ String versionName = pi.versionName == null ? "null" : pi.versionName;
+ String versionCode = pi.versionCode + "";
+ infos.put("versionName", versionName);
+ infos.put("versionCode", versionCode);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "an error occured when collect package info", e);
+ }
+ Field[] fields = Build.class.getDeclaredFields();
+ for (Field field : fields) {
+ try {
+ field.setAccessible(true);
+ infos.put(field.getName(), field.get(null).toString());
+ Log.d(TAG, field.getName() + " : " + field.get(null));
+ } catch (Exception e) {
+ Log.e(TAG, "an error occured when collect crash info", e);
+ }
+ }
+ }
+
+ /**
+ * 保存错误信息到文件中
+ *
+ * @param ex
+ * @return 返回文件名称,便于将文件传送到服务器
+ */
+ private String saveCatchInfo2File(Throwable ex) {
+ ex.printStackTrace();
+ Log.i(TAG, "saveCatchInfo2File Throwable:"+ex);
+
+ StringBuffer sb = new StringBuffer();
+ for (Map.Entry<String, String> entry : infos.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+ sb.append(key + "=" + value + "\n");
+ }
+
+ Writer writer = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(writer);
+ ex.printStackTrace(printWriter);
+ Throwable cause = ex.getCause();
+ while (cause != null) {
+ cause.printStackTrace(printWriter);
+ cause = cause.getCause();
+ }
+ printWriter.close();
+ String result = writer.toString();
+ sb.append(result);
+ try {
+ long timestamp = System.currentTimeMillis();
+ String time = formatter.format(new Date());
+ String fileName = "crash-" + time + "-" + timestamp + ".log";
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ String path = "/mnt/sdcard/crash/";
+ File dir = new File(path);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ FileOutputStream fos = new FileOutputStream(path + fileName);
+ fos.write(sb.toString().getBytes());
+ //发送给开发人员
+ sendCrashLog2PM(path+fileName);
+ fos.close();
+ }
+ return fileName;
+ } catch (Exception e) {
+ Log.e(TAG, "an error occured while writing file...", e);
+ }
+ return null;
+ }
+
+ /**
+ * 将捕获的导致崩溃的错误信息发送给开发人员
+ *
+ * 目前只将log日志保存在sdcard 和输出到LogCat中,并未发送给后台。
+ */
+ private void sendCrashLog2PM(String fileName){
+ Log.i(TAG, "asendCrashLog2PM fileName:"+fileName);
+ if(!new File(fileName).exists()){
+ Toast.makeText(mContext, "日志文件不存在!", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ FileInputStream fis = null;
+ BufferedReader reader = null;
+ String s = null;
+ try {
+ fis = new FileInputStream(fileName);
+ reader = new BufferedReader(new InputStreamReader(fis, "GBK"));
+ while(true){
+ s = reader.readLine();
+ if(s == null) break;
+ //由于目前尚未确定以何种方式发送,所以先打出log日志。
+ //Log.i("info", s.toString());
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }finally{ // 关闭流
+ try {
+ reader.close();
+ fis.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static interface CrashListener{
+ void onCrash();
+ }
+}
diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java b/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java
index 221f070..6d271e4 100644
--- a/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java
+++ b/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java
@@ -51,7 +51,7 @@
int position = logArrays.size() +2;
Response response;
try {
- //request = encryptRequest(request);//加密
+ request = encryptRequest(request);//加密
response = chain.proceed(request);
logArrays.addAll(getResponseLog(response));
Log.d(TAG,"hashcode:"+hashCode);
diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/api/LoginApiCenter.java b/app/src/main/java/com/runt/open/mvvm/retrofit/api/LoginApiCenter.java
index 7e03dc2..c41d848 100644
--- a/app/src/main/java/com/runt/open/mvvm/retrofit/api/LoginApiCenter.java
+++ b/app/src/main/java/com/runt/open/mvvm/retrofit/api/LoginApiCenter.java
@@ -1,24 +1,65 @@
package com.runt.open.mvvm.retrofit.api;
-import com.runt.open.mvvm.ui.login.LoggedInUser;
+import com.runt.open.mvvm.config.Configuration;
+import com.runt.open.mvvm.data.Results;
import io.reactivex.Observable;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
+import retrofit2.http.Url;
/**
* Created by Administrator on 2021/11/15 0015.
*/
public interface LoginApiCenter {
+ /**
+ * 密码登录
+ * @param phone
+ * @param pass
+ * @return
+ */
@FormUrlEncoded
@POST("login")
- Observable<LoggedInUser> login(@Field("phone") String phone,@Field("pass") String pass);
+ Observable<Results.LoggedInUser> login(@Field(Configuration.KEY_PHONE) String phone, @Field("pass") String pass);
+
+ /**
+ * 验证码登录
+ * @param phone
+ * @param code
+ * @return
+ */
+ @FormUrlEncoded
+ @POST("loginCode")
+ Observable<Results.LoggedInUser> loginByCode(@Field(Configuration.KEY_PHONE) String phone, @Field(Configuration.KEY_CODE) String code);
@FormUrlEncoded
- @POST("login")
- Observable<LoggedInUser> loginByCode(@Field("phone") String phone,@Field("code") String code);
+ @POST
+ Observable<Results.StringApiResult> getVerifyCode(@Url String url, @Field(Configuration.KEY_PHONE) String phone, @Field(Configuration.KEY_CODE) String code, @Field("time") String time);
+
+ /**
+ * 重置密码
+ * @param phone
+ * @param sms
+ * @param newPass
+ * @return
+ */
+ @FormUrlEncoded
+ @POST("verifySMSReSetLoginPwd")
+ Observable<Results.StringApiResult> resetLoginPwd(@Field(Configuration.KEY_PHONE) String phone,@Field("sms") String sms, @Field("pass") String newPass);
+
+
+ /**
+ * 注册
+ * @param phone
+ * @param sms
+ * @param pass
+ * @return
+ */
+ @FormUrlEncoded
+ @POST("registerCustomer")
+ Observable<Results.StringApiResult> register(@Field(Configuration.KEY_USERNAME) String phone,@Field("sms") String sms, @Field("pass") String pass);
}
diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java b/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java
index 7024299..3a4ac2c 100644
--- a/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java
+++ b/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java
@@ -1,5 +1,6 @@
package com.runt.open.mvvm.retrofit.observable;
+import android.accounts.NetworkErrorException;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -41,14 +42,16 @@
Log.i("subscribe","onError");
try {
- Log.e(TAG,this.getClass().getSimpleName()+" "+throwable.getMessage());
+ Log.e(TAG,this.getClass().getSimpleName()+" mes:"+throwable.getMessage());
Class<M> entityClass = (Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
M t = entityClass.newInstance();//实例化一个泛型
t.code = 410;
if( throwable instanceof SocketTimeoutException){
t.msg = "服务请求超时,请稍候再试";//设置错误信息
- }else{
+ }else if( throwable instanceof NetworkErrorException){
t.msg = "网络连接不畅,请检查您的网络设置";//设置错误信息
+ }else{
+ t.msg = throwable.getMessage();//设置错误信息
}
resultLive.setValue(t);
} catch (ClassCastException e) {
diff --git a/app/src/main/java/com/runt/open/mvvm/ui/login/CodeTimer.java b/app/src/main/java/com/runt/open/mvvm/ui/login/CodeTimer.java
new file mode 100644
index 0000000..764b79a
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/ui/login/CodeTimer.java
@@ -0,0 +1,40 @@
+package com.runt.open.mvvm.ui.login;
+
+import android.os.CountDownTimer;
+import android.widget.TextView;
+
+import com.runt.open.mvvm.R;
+
+/**
+ * My father is Object, ites purpose of
+ *
+ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-2-23.
+ */
+public class CodeTimer extends CountDownTimer {
+
+ TextView txtGetCode;
+
+ public CodeTimer(long millisInFuture, long countDownInterval, TextView txtGetCode) {
+ super(millisInFuture, countDownInterval);
+ this.txtGetCode = txtGetCode;
+ }
+
+ public void startUp(){
+ txtGetCode.setEnabled(false);
+ txtGetCode.setTextColor(txtGetCode.getContext().getResources().getColor(R.color.txt_enable));
+ start();
+ }
+
+ @Override
+ public void onTick(long l) {
+ txtGetCode.setText(String.format("(%s)", l/1000));
+ }
+
+ @Override
+ public void onFinish() {
+ txtGetCode.setEnabled(true);
+ txtGetCode.setTextColor(txtGetCode.getContext().getResources().getColor(R.color.link));
+ txtGetCode.setText(txtGetCode.getContext().getResources().getString(R.string.get_verify_code));
+ }
+
+}
diff --git a/app/src/main/java/com/runt/open/mvvm/ui/login/LoggedInUser.java b/app/src/main/java/com/runt/open/mvvm/ui/login/LoggedInUser.java
deleted file mode 100644
index 8a5ad19..0000000
--- a/app/src/main/java/com/runt/open/mvvm/ui/login/LoggedInUser.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.runt.open.mvvm.ui.login;
-
-import com.runt.open.mvvm.data.BaseApiResult;
-
-/**
- * Created by Administrator on 2021/11/15 0015.
- */
-public class LoggedInUser extends BaseApiResult<UserBean> {
-
-}
diff --git a/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java b/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java
index 866420b..eda4bd3 100644
--- a/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java
+++ b/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java
@@ -3,9 +3,14 @@
import androidx.lifecycle.MutableLiveData;
import com.runt.open.mvvm.base.model.BaseViewModel;
+import com.runt.open.mvvm.data.Results;
import com.runt.open.mvvm.retrofit.api.LoginApiCenter;
import com.runt.open.mvvm.retrofit.observable.HttpObserver;
import com.runt.open.mvvm.retrofit.utils.RetrofitUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
import io.reactivex.Observable;
@@ -14,17 +19,132 @@
*/
public class LoginViewModel extends BaseViewModel {
- MutableLiveData<LoggedInUser> loginResult = new MutableLiveData<>();
+ LoginApiCenter loginApi;
- public MutableLiveData<LoggedInUser> getLoginResult() {
+ public LoginViewModel() {
+ loginApi = RetrofitUtils.getInstance().getRetrofit(LoginApiCenter.class);
+ }
+
+ MutableLiveData<Results.LoggedInUser> loginResult = new MutableLiveData<>();
+ MutableLiveData<Results.StringApiResult> verifyResult = new MutableLiveData<>();
+ MutableLiveData<Results.StringApiResult> resetResult = new MutableLiveData<>();
+ MutableLiveData<Results.StringApiResult> registerResult = new MutableLiveData<>();
+
+ public MutableLiveData<Results.LoggedInUser> getLoginResult() {
return loginResult;
}
- public void login(String username, String password) {
- // can be launched in a separate asynchronous job
- final Observable<LoggedInUser> userObservable = RetrofitUtils.getInstance().getRetrofit(LoginApiCenter.class).login(username, password);
- httpObserverOn(userObservable,new HttpObserver<LoggedInUser>(loginResult){});
+ public MutableLiveData<Results.StringApiResult> getVerifyResult() {
+ return verifyResult;
}
+ /**
+ * 密码登录
+ * @param username
+ * @param password
+ */
+ public void login(String username, String password) {
+ // can be launched in a separate asynchronous job
+ final Observable<Results.LoggedInUser> userObservable = loginApi.login(username, password);
+ httpObserverOnLoading(userObservable,new HttpObserver<Results.LoggedInUser>(loginResult){});
+ }
+ /**
+ * 验证码登录
+ * @param phone
+ * @param code
+ */
+ public void loginByCode(String phone,String code){
+ httpObserverOnLoading(loginApi.loginByCode(phone,code),
+ new HttpObserver<Results.LoggedInUser>(loginResult){});
+ }
+
+ /**
+ * 重置密码
+ * @param phone
+ * @param sms
+ * @param pass
+ */
+ public void resetPwd(String phone,String sms,String pass){
+ httpObserverOnLoading(loginApi.resetLoginPwd(phone, sms, pass), new HttpObserver<Results.StringApiResult>(resetResult) {});
+ }
+
+ /**
+ * 注册
+ * @param phone
+ * @param sms
+ * @param pass
+ */
+ public void register(String phone,String sms,String pass){
+ httpObserverOnLoading(loginApi.register(phone, sms, pass), new HttpObserver<Results.StringApiResult>(resetResult) {});
+ }
+
+ /**
+ * 注册密码
+ * @param phone
+ */
+ public void getRegisterSMS(String phone){
+ getVerifyCode("getRegisterSMS",phone);
+ }
+
+ /**
+ * 忘记密码
+ * @param phone
+ */
+ public void getForgetSMS(String phone){
+ getVerifyCode("getForgetSMS",phone);
+ }
+
+ /**
+ * 登录验证码
+ * @param phone
+ */
+ public void getLoginSMS(String phone){
+ getVerifyCode("getLoginSMS",phone);
+ }
+
+ /**
+ * 获取验证码
+ * @param url 验证码地址
+ * @param phone 手机号
+ */
+ public void getVerifyCode(String url,String phone){
+ String time = new Date().getTime()+"";
+ httpObserverOnLoading(loginApi.getVerifyCode(url, phone, randomString(phone, time), time), new HttpObserver<Results.StringApiResult>(verifyResult){});
+ }
+
+ /**
+ * 随机字符串
+ * @param phone
+ * @param time
+ * @return
+ */
+ private String randomString(String phone,String time){
+ int p = (int) Math.round(phone.length()/6.0);
+ int t = time.length()/6;
+ List<String> list = new ArrayList<String>();
+ for(int i = 0 ; i < 6 ; i ++){
+ String str = "";
+ if(i*p>phone.length()){
+ str = phone.substring((i-1)*p);
+ }else if((i+1)*p>phone.length()){
+ str = phone.substring(i*p);
+ }else{
+ str = phone.substring(i*p,(i+1)*p);
+ }
+ String num = ((Integer.parseInt(str)*Long.parseLong(time))+"") ;
+ list.add(num);
+ }
+ //return sb.toString();
+ return plusSingle2(list);
+ }
+
+ private String plusSingle2(List<String> list){
+ StringBuilder sb = new StringBuilder();
+ for(int i = 0 ; i < list.size() ; i ++){
+ sb.append(list.get(i).substring(list.get(i).length()-2<0?0:list.get(i).length()-2));
+ }
+ return sb.toString();
+
+ }
}
diff --git a/app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java b/app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java
new file mode 100644
index 0000000..ab84fd8
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java
@@ -0,0 +1,287 @@
+package com.runt.open.mvvm.ui.login;
+
+import android.content.Intent;
+import android.view.View;
+import android.widget.EditText;
+
+import com.google.gson.Gson;
+import com.runt.open.mvvm.R;
+import com.runt.open.mvvm.base.activities.BaseActivity;
+import com.runt.open.mvvm.config.Configuration;
+import com.runt.open.mvvm.databinding.ActivityLoginBinding;
+import com.runt.open.mvvm.listener.CustomClickListener;
+import com.runt.open.mvvm.ui.web.WebViewActivity;
+import com.runt.open.mvvm.util.AlgorithmUtils;
+import com.runt.open.mvvm.util.MyLog;
+import com.runt.open.mvvm.util.PhoneUtil;
+
+import java.util.Date;
+
+/**
+ * My father is Object, ites purpose of
+ *
+ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/1/29.
+ */
+public class RegisterLoginActivity extends BaseActivity<ActivityLoginBinding,LoginViewModel> {
+ final String VERIFY_CODE = "verify_code";
+ final String TAG = "RegisterLoginActivity";
+ int type = 0;//0 登录,1忘记密码,2注册,-1短信登录
+
+ @Override
+ public void initViews() {
+ binding.txtGetVerify.setOnClickListener(onclick);
+ binding.txtForgot.setOnClickListener(onclick);
+ binding.txtLogin.setOnClickListener(onclick);
+ binding.txtRegister.setOnClickListener(onclick);
+ binding.txtPrivacy.setOnClickListener(onclick);
+ long getTime = getLongProjectPrefrence(VERIFY_CODE);
+ long cha = new Date().getTime() - getTime;
+ if(cha <1000*60){
+ CodeTimer codeTimer = new CodeTimer(cha, 1000, binding.txtGetVerify);
+ codeTimer.startUp();
+ }
+ changeView();
+ binding.editPhone.setText(getStringProjectPrefrence(Configuration.KEY_USERNAME));
+ viewModel.getVerifyResult().observe(this, stringApiResult -> {
+ if(stringApiResult.code == 200){
+
+ }else{
+ showToast(stringApiResult.msg);
+ }
+ });
+ viewModel.getLoginResult().observe(this,loggedInUser -> {
+ if(loggedInUser.code == 200){
+ putBooleanProjectPrefrence(Configuration.IS_LOGIN,true);
+ putStringProjectPrefrence(Configuration.KEY_USERNAME,binding.editPhone.getText().toString());
+
+ UserBean user = new Gson().fromJson(new Gson().toJson(loggedInUser.data) ,UserBean.class);
+ UserBean.setUser(user);
+ putStringProjectPrefrence(Configuration.KEY_TOKEN, user.getToken());
+ MyLog.i("registerlogin",user.toString());
+ showToast(R.string.login_success);
+ setResult(RESULT_CODE_SUCESS);
+ finish();
+ }else{
+ showToast(loggedInUser.msg);
+ }
+ });
+ }
+
+ CustomClickListener onclick = new CustomClickListener() {
+ @Override
+ protected void onSingleClick(View view) {
+ switch (view.getId()){
+ case R.id.button:
+ submit();
+ break;
+ case R.id.txt_get_verify:
+
+ String phone = binding.editPhone.getText().toString();
+ if(!verifyPhone(phone)){//验证手机
+ return;
+ }
+ if(type==2){//获取注册验证码
+ viewModel.getRegisterSMS(phone);
+ }else if(type ==1){
+ viewModel.getForgetSMS( phone);
+ }else if(type == -1){
+ viewModel.getLoginSMS( phone);
+ }
+ break;
+ case R.id.txt_privacy:
+ startActivity(new Intent(mContext, WebViewActivity.class).putExtra(PARAMS_URL,"http://www.hefan.space/privacyPolicy.html").putExtra(PARAMS_TITLE,"隐私政策"));
+ break;
+ case R.id.txt_register:
+ type = 2;
+ changeView();
+ break;
+ case R.id.txt_forgot:
+ type = 1;
+ changeView();
+ break;
+ case R.id.txt_login:
+ if(type != 0 ){
+ type = 0;
+ }else {
+ type = -1;
+ }
+ changeView();
+ break;
+ }
+ }
+ };
+
+
+ /**
+ * 修改页面布局
+ */
+ private void changeView(){
+ binding.button.setEnabled(true);
+ binding.txtRegister.setVisibility(View.VISIBLE);
+ binding.checkbox.setVisibility(View.GONE);
+ binding.txtPrivacy.setVisibility(View.GONE);
+ switch (type){
+ case -1://短信登录
+ binding.editVerifyCode.setVisibility(View.VISIBLE);
+ binding.txtGetVerify.setVisibility(View.VISIBLE);
+ binding.editPass.setVisibility(View.GONE);
+ binding.editPassRepeat.setVisibility(View.GONE);
+ binding.txtForgot.setVisibility(View.VISIBLE);
+ binding.txtLogin.setText(getResources().getString(R.string.login));
+ binding.button.setText(getResources().getString(R.string.login));
+ binding.checkbox.setVisibility(View.VISIBLE);
+ binding.txtPrivacy.setVisibility(View.VISIBLE);
+ break;
+ case 0://登录
+ binding.editVerifyCode.setVisibility(View.GONE);
+ binding.txtGetVerify.setVisibility(View.GONE);
+ binding.editPass.setVisibility(View.VISIBLE);
+ binding.editPassRepeat.setVisibility(View.GONE);
+ binding.txtForgot.setVisibility(View.VISIBLE);
+ binding.txtLogin.setText(getResources().getString(R.string.msg_login));
+ binding.button.setText(getResources().getString(R.string.login));
+ break;
+ case 1://忘记密码
+ binding.txtForgot.setVisibility(View.INVISIBLE);
+ binding.editVerifyCode.setVisibility(View.VISIBLE);
+ binding.txtGetVerify.setVisibility(View.VISIBLE);
+ binding.editPass.setVisibility(View.VISIBLE);
+ binding.editPassRepeat.setVisibility(View.VISIBLE);
+ binding.txtLogin.setText(getResources().getString(R.string.login));
+ binding.button.setText(getResources().getString(R.string.str_confirm));
+ break;
+ case 2://注册
+ binding.checkbox.setVisibility(View.VISIBLE);
+ binding.txtPrivacy.setVisibility(View.VISIBLE);
+ binding.txtRegister.setVisibility(View.INVISIBLE);
+ binding.editVerifyCode.setVisibility(View.VISIBLE);
+ binding.txtGetVerify.setVisibility(View.VISIBLE);
+ binding.editPass.setVisibility(View.VISIBLE);
+ binding.editPassRepeat.setVisibility(View.VISIBLE);
+ binding.txtLogin.setText(getResources().getString(R.string.login));
+ binding.button.setText(getResources().getString(R.string.register));
+ break;
+ }
+ clearText(binding.editPassRepeat,binding.editPass,binding.editPhone,binding.editVerifyCode);
+ }
+
+ private void clearText(EditText... editTextes){
+ for(EditText editText :editTextes) {
+ editText.setText("");
+ }
+ }
+
+
+
+
+ /**
+ * 提交数据
+ */
+ public void submit(){
+ String phone = binding.editPhone.getText().toString();
+ String pass = binding.editPass .getText().toString();
+ String veriCode = binding.editVerifyCode.getText().toString();
+ String invite = binding.editPassRepeat.getText().toString();
+ if(!verifyPhone(phone)){//验证手机
+ return;
+ }
+ switch (type){
+ case -1://短信登录
+ if(veriCode.length() == 0){//验证码
+ showToast(R.string.input_verify_code);
+ return;
+ }
+ if(!binding.checkbox.isChecked()){
+ showToast("请阅读并勾选《隐私条款》");
+ return;
+ }
+ viewModel.loginByCode(phone,veriCode);
+ break;
+ case 0:
+ if(!verifyPassWord(pass)){//验证密码
+ return;
+ }
+ viewModel.login(phone,pass);
+ break;
+ case 1:
+ if(!verifyPassWord(pass)){//验证密码
+ return;
+ }
+ if(veriCode.length() == 0){//验证码
+ showToast(R.string.input_verify_code);
+ return;
+ }
+
+ //新密码
+ if(invite.length() == 0){
+ showToast(R.string.input_pass);
+ return;
+ } else if(!invite.equals(pass)){
+ showToast(R.string.str_new_verify_failed);
+ return;
+ }
+ viewModel.resetPwd(phone,veriCode,pass);
+ break;
+ case 2://注册
+ if(!verifyPassWord(pass)){//验证密码
+ return;
+ }
+ if(veriCode.length() == 0){//验证码
+ showToast(R.string.input_verify_code);
+ return;
+ }
+ if(!binding.checkbox.isChecked()){
+ showToast("请阅读并勾选《隐私条款》");
+ return;
+ }
+ viewModel.register(phone,veriCode,pass);
+ break;
+ }
+ }
+
+ /**
+ * 验证密码
+ * @param pass
+ * @return
+ */
+ public boolean verifyPassWord(String pass){
+
+ if(pass.length() == 0){
+ showToast(R.string.input_pass);
+ return false;
+ } else if(!verifyPass(pass)){
+ showToast(R.string.str_pass_format_failed);
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
+ * 验证手机号
+ * @param phone
+ * @return
+ */
+ public boolean verifyPhone(String phone ){
+
+ if(phone.length() == 0){
+ showToast(R.string.input_phone);
+ return false;
+ }else if(phone.length()<5 || !PhoneUtil.isMobileNO(phone)){
+ showToast(R.string.str_phone_format_failed);
+ return false;
+ }
+ return true;
+
+ }
+
+
+ /**
+ * 验证密码
+ * @param pass
+ * @return
+ */
+ public boolean verifyPass(String pass){
+ return AlgorithmUtils.pwdLevel(pass)>1 && pass.length()>=6 && pass.length() <=12;
+ }
+}
diff --git a/app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java b/app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java
new file mode 100644
index 0000000..d41521c
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java
@@ -0,0 +1,159 @@
+package com.runt.open.mvvm.ui.web;
+
+import android.os.Handler;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.animation.LayoutAnimationController;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Toast;
+
+import com.runt.open.mvvm.base.activities.BaseActivity;
+import com.runt.open.mvvm.base.model.BaseViewModel;
+import com.runt.open.mvvm.databinding.ActivityWebBinding;
+import com.runt.open.mvvm.util.MyAnimations;
+import com.runt.open.mvvm.util.MyLog;
+
+/**
+ * My father is Object, ites purpose of
+ *
+ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-9-16.
+ */
+public class WebViewActivity extends BaseActivity<ActivityWebBinding, BaseViewModel> {
+
+ private String url;
+ private int linProgressWidth;
+
+ @Override
+ public void initViews() {
+ url = getIntent().getSerializableExtra(PARAMS_URL)+"";
+ setTitle(getIntent().getSerializableExtra(PARAMS_TITLE)+"");
+ initCompent();
+ }
+
+
+ int count = 100;
+ int index = 100;
+ private void initCompent(){
+ binding.browser.getSettings().setJavaScriptEnabled(true);
+ binding.browser.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
+ //跳转至拼接好的地址
+ //mBaseHandler.sendMessage(msg);//http://192.168.5.156:8080/MyFinance/gd16/1.html
+ binding.browser.loadUrl(url);
+ binding.browser.setWebViewClient(new myWebViewClient());
+ binding.browser.setWebChromeClient(new WebChromeClient(){
+
+ @Override
+ public void onProgressChanged(WebView view,final int newProgress) {
+ MyLog.i("onProgressChanged","--newProgress:--"+newProgress);
+ MyLog.i("onProgressChanged","--binding.viewProgressbar:--"+binding.viewProgressbar.getWidth());
+ final LayoutAnimationController.AnimationParameters animation= new LayoutAnimationController.AnimationParameters(); //得到一个LayoutAnimationController对象;
+ animation.index =index++ ;
+ animation.count = count++ ;
+ if (newProgress == 100) {
+ MyAnimations.hideAnimaInSitu(binding.linProgressbar);
+ MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),0,0,0,binding.viewProgressbar);
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ binding.linProgressbar.setVisibility(View.GONE);
+ }
+ },MyAnimations.ANIMA_TIME);
+ } else {
+
+ if (View.VISIBLE != binding.linProgressbar.getVisibility()) {
+ MyAnimations.showAnimaInSitu(binding.linProgressbar);
+ if(linProgressWidth==0){
+ final ViewTreeObserver vto = binding.linProgressbar.getViewTreeObserver();
+ vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ public boolean onPreDraw() {
+ linProgressWidth = binding.linProgressbar.getMeasuredWidth();
+ binding.viewProgressbar.setTranslationX(0-linProgressWidth);
+ binding.linProgressbar.getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
+ });
+ }else{
+ binding.viewProgressbar.setTranslationX(0-linProgressWidth);
+ }
+
+ }
+ if(linProgressWidth!=0){
+ MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),0-linProgressWidth+linProgressWidth/100*newProgress,0,0,binding.viewProgressbar,MyAnimations.ANIMA_TIME*3);
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),binding.viewProgressbar.getTranslationX()+300,0,0,binding.viewProgressbar,MyAnimations.ANIMA_TIME*10);
+ }
+ },MyAnimations.ANIMA_TIME*3);
+ }
+
+ }
+ super.onProgressChanged(view, newProgress);
+ }
+
+ });
+
+ binding.browser.getSettings().setSavePassword(false);
+ //Toast.makeText(mContext,"进入浏览器",Toast.LENGTH_SHORT).show();
+ String Scale = String.valueOf(binding.browser.getScale());
+ MyLog.i("Runt","--Scale:--"+Scale);
+ int screenDensity=getResources().getDisplayMetrics().densityDpi;
+ MyLog.i("Runt", "--screenDensity:--"+String.valueOf(screenDensity)); //60-160-240
+ }
+
+
+
+
+ private class myWebViewClient extends WebViewClient {
+
+ /**
+ * 每加载一张图片资源执行一次
+ */
+ @Override
+ public void onLoadResource(WebView view, String url) {
+ // TODO Auto-generated method stub
+ super.onLoadResource(view, url);
+ //MyLog.i("WebView", "onLoadResource "+url);
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ hideProgressBar();
+ //MyLog.i("WebView", "onPageFinished "+url);
+ }
+
+ /**
+ * 获取页面跳转的链接
+ */
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ // TODO Auto-generated method stub
+ //MyLog.i("UrlLoading", "UrlLoading 正在跳转页面"+url);
+ view.loadUrl(url);
+ return true;
+ }
+
+ @Override
+ public void onReceivedError(WebView view, int errorCode,
+ String description, String failingUrl) {
+ // TODO Auto-generated method stub
+ super.onReceivedError(view, errorCode, description, failingUrl);
+ Toast.makeText(mContext, "加载失败,请稍候再试", Toast.LENGTH_SHORT).show();
+ hideProgressBar();
+ }
+ }
+
+ private void hideProgressBar(){
+ MyAnimations.hideAnimaInSitu(binding.linProgressbar);
+ MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),0,0,0,binding.viewProgressbar);
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ binding.linProgressbar.setVisibility(View.GONE);
+ }
+ },MyAnimations.ANIMA_TIME*2);
+ }
+}
diff --git a/app/src/main/java/com/runt/open/mvvm/util/Configuration.java b/app/src/main/java/com/runt/open/mvvm/util/Configuration.java
deleted file mode 100644
index c4adb9c..0000000
--- a/app/src/main/java/com/runt/open/mvvm/util/Configuration.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.runt.open.mvvm.util;
-
-/**
- * Created by xanarry on 2016/5/22.
- */
-public class Configuration {
-
-
- public static final int REQUEST_CODE_PIC = 303;
-
-
- public final static String MESS_TIP_NET_ERROR = "网络连接不畅,请稍后再试!!!";
- public final static String KEY_MES_CODE= "code";
- public final static String KEY_MES_TIME= "time";
- public final static String KEY_MES_MESSAGE= "msg";
- public final static String KEY_MES_ERROR= "error";
- public final static String KEY_CODE_SUCCESS= "0";//code 0 成功
- public final static int KEY_CODE_INFO= 101;//修改资料
- public final static String KEY_USER = "user";
- public final static String KEY_ADVERT= "advert";
- public final static String KEY_DATA= "data";
- public final static String KEY_FILES= "files";
- public final static String KEY_SCREEN_TYPE = "screen_type";//屏幕类型
- public final static String KEY_SCREEN_FILES= "screen_files";//播放的资源文件列表
- public final static String KEY_NAME= "name";
- public final static String KEY_MARk= "mark";
- public final static String KEY_ORDER= "order";
- public final static String FILENAME_MK = "fileName";
- public final static String FILEPATH = "path";
- public final static String STR_APPLY_DATA = "apply datas";
- public final static String STR_FILE_PLAN_FAILED = "file plan failed";
- public final static String STR_START_FILE_PLAN = "start file plan";
- public final static String STR_FINISHED_FILE_PLAN = "finished plan";
- public final static String FILESIZE_MK = "fileSize";
-
- public static final String KEY_EXTRAS = "extras";
- public static final String KEY_USERID = "customerId";
- public static final String KEY_TOKEN = "token";
- public static final String KEY_USERNAME = "username";
- public static final String KEY_PHONE = "phone";
- public static final String KEY_USERPASS = "userpass";
- public static final String MESSAGE_RECEIVED_ACTION = "MESSAGE_RECEIVED_ACTION";
-
- public static final String KEY_REGION = "region",
- IS_LOGIN = "is_login";
-
-
-}
diff --git a/app/src/main/java/com/runt/open/mvvm/util/MyAnimations.java b/app/src/main/java/com/runt/open/mvvm/util/MyAnimations.java
new file mode 100644
index 0000000..b3faaac
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/util/MyAnimations.java
@@ -0,0 +1,477 @@
+package com.runt.open.mvvm.util;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.TranslateAnimation;
+import android.widget.RelativeLayout;
+
+import com.facebook.rebound.SimpleSpringListener;
+import com.facebook.rebound.Spring;
+import com.facebook.rebound.SpringConfig;
+import com.facebook.rebound.SpringSystem;
+import com.runt.open.mvvm.R;
+
+/**
+ * Created by Administrator on 2017/11/30.
+ */
+public class MyAnimations {
+
+ public static final int ANIMA_TIME = 300;
+ public static final float MOVE_SPACE = 1;
+ public static final float SITU = 0;
+
+
+
+ /**
+ * 移动控件
+ * @param x x初始位置
+ * @param distanceX x移动的距离
+ * @param y y初始位置
+ * @param distanceY y移动的距离
+ * @param view
+ */
+ public static void makeViewMove(float x ,float distanceX , float y ,float distanceY, View view){
+ setAnimator("translationY", y, distanceY,view,ANIMA_TIME);
+ setAnimator("translationX", x, distanceX,view,ANIMA_TIME);
+ }
+ /**
+ * 移动控件
+ * @param x x初始位置
+ * @param distanceX x移动的距离
+ * @param y y初始位置
+ * @param distanceY y移动的距离
+ * @param view
+ */
+ public static void makeViewMove(float x , float distanceX , float y , float distanceY, View view, int animTime){
+ setAnimator("translationY", y, distanceY,view,animTime);
+ setAnimator("translationX", x, distanceX,view,animTime);
+ }
+
+ private static void setAnimator(String attribute, float from, float to, View view, int animTime){
+ ObjectAnimator.ofFloat(view, attribute, from, to).setDuration(animTime).start();
+ }
+ public static void setLayoutMargin(View view, int left, int top, int right, int bottom)
+ {
+ //克隆view的width、height、margin的值生成margin对象
+ ViewGroup.MarginLayoutParams margin=new ViewGroup.MarginLayoutParams(view.getLayoutParams());
+ //设置新的边距
+ margin.setMargins(left, top, right, bottom);
+ //把新的边距生成layoutParams对象
+ RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(margin);
+ //设制view的新的位置
+ view.setLayoutParams(layoutParams);
+ }
+ /**
+ * 原地不动
+ * @return
+ */
+ private static TranslateAnimation makeInSitu(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,SITU,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,SITU);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+
+ /**
+ * 从顶部显示
+ * @return
+ */
+ private static TranslateAnimation makeInFromTop(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,SITU,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,0-MOVE_SPACE,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,SITU);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+ /**
+ * 从底部显示
+ * @return
+ */
+ private static TranslateAnimation makeInFromBottom(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,SITU,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,MOVE_SPACE,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,SITU);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+ /**
+ * 从左侧显示
+ * @return
+ */
+ private static TranslateAnimation makeInFromLeft(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0-MOVE_SPACE,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,SITU);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+ /**
+ * 从右侧显示
+ * @return
+ */
+ private static TranslateAnimation makeInFromRight(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,MOVE_SPACE,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,SITU);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+
+ /**
+ * 向上隐藏
+ * @return
+ */
+ private static TranslateAnimation makeOutToTop(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,SITU,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,0-MOVE_SPACE);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+ /**
+ * 向左隐藏
+ * @return
+ */
+ private static TranslateAnimation makeOutToLeft(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,SITU,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,0-MOVE_SPACE,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,SITU);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+ /**
+ * 向右隐藏
+ * @return
+ */
+ private static TranslateAnimation makeOutToRight(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,SITU,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,MOVE_SPACE,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,SITU);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+ /**
+ * 向下隐藏
+ * @return
+ */
+ private static TranslateAnimation makeOutToButtom(){
+ TranslateAnimation mAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF,SITU,//大于0 则从右向当前位置移动,反之则从左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从当前位置向右移动,反之则向左
+ Animation.RELATIVE_TO_SELF,SITU,//大于0 则从下方向当前位置,反之则从上方
+ Animation.RELATIVE_TO_SELF,MOVE_SPACE);//大于0从当前位置向下移动,反之则向上方
+ mAction.setDuration(ANIMA_TIME);
+ return mAction;
+ }
+
+
+
+ /***
+ * 动画显示 从右向左左显示
+ *
+ * @param view
+ */
+ public static void showAnimaRightToLeft(View view) {
+ view.setVisibility(View.VISIBLE);
+ Animation mAni;
+ mAni = makeInFromRight();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+
+ /***
+ * 动画显示 从右向左左显示
+ *
+ * @param view
+ */
+ public static void showAnimaLeftToRight(View view) {
+ view.setVisibility(View.VISIBLE);
+ Animation mAni;
+ mAni = makeInFromLeft();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+ /**
+ * 动画隐藏 从下往上
+ *
+ * @param view
+ */
+ public static void hideAnimaBottomToTop(View view) {
+ view.setVisibility(View.INVISIBLE);
+ Animation mAni;
+ mAni = makeOutToTop();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+ /**
+ * 动画隐藏 从左往右
+ *
+ * @param view
+ */
+ public static void hideAnimaLeftToRight(View view) {
+ view.setVisibility(View.INVISIBLE);
+ Animation mAni;
+ mAni = makeOutToRight();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+ /**
+ * 动画隐藏 从右往左
+ *
+ * @param view
+ */
+ public static void hideAnimaRightToLeft(View view) {
+ view.setVisibility(View.INVISIBLE);
+ Animation mAni;
+ mAni = makeOutToLeft();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+
+ /**
+ * 动画隐藏 原地
+ *
+ * @param view
+ */
+ public static void hideAnimaInSitu(View view) {
+ view.setVisibility(View.INVISIBLE);
+ Animation mAni;
+ mAni = makeInSitu();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+
+ /**
+ * 动画显示 原地
+ *
+ * @param view
+ */
+ public static void showAnimaInSitu(View view) {
+ view.setVisibility(View.VISIBLE);
+ Animation mAni;
+ mAni = makeInSitu();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+
+
+ /**
+ * 动画显示 从上往下走
+ *
+ * @param view
+ */
+ public static void showAnimaTopToBottom(View view) {
+ view.setVisibility(View.VISIBLE);
+ Animation mAni;
+ mAni = makeInFromTop();
+ mAni.setDuration(ANIMA_TIME);
+ view.setAnimation(mAni);
+ }
+
+ /**
+ * 冒泡式显示控件
+ * @param view
+ */
+ public static void showReBound(final View view){
+ Log.i("","showReBound view:"+view);
+ view.setVisibility(View.GONE);
+ showAnimaInSitu(view);
+ SpringSystem springSystem = SpringSystem.create();
+ final Spring spring = springSystem.createSpring();
+ spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(100,7));//qcTension拉力和qcFriction摩擦力参数
+ spring.addListener(new SimpleSpringListener() {
+ @Override
+ public void onSpringUpdate(Spring spring) {
+ float value = (float) spring.getCurrentValue();
+ float scale = value;
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ }
+ });
+ spring.setEndValue(1);//控件拉伸收缩的倍率
+ }
+
+ /**
+ * 冒泡式放大控件
+ * @param view
+ */
+ public static void showReBoundBig(final View view){
+ Log.i("","showReBound view:"+view);
+ view.setVisibility(View.GONE);
+ showAnimaInSitu(view);
+ SpringSystem springSystem = SpringSystem.create();
+ final Spring spring = springSystem.createSpring();
+ spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(100,7));//qcTension拉力和qcFriction摩擦力参数
+ spring.addListener(new SimpleSpringListener() {
+ @Override
+ public void onSpringUpdate(Spring spring) {
+ float value = (float) spring.getCurrentValue();
+ float scale = value;
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ }
+ });
+ spring.setEndValue(3);//控件拉伸收缩的倍率
+ }
+
+ /**
+ * 收缩式 隐藏
+ * @param view
+ * @param context
+ */
+ public static void hideReBound(final View view, final Context context){
+ /*showReBound(view);
+ @SuppressLint("ResourceType") Animator animator = AnimatorInflater.loadAnimator(context, R.anim.anima_make_none);
+ animator.setTarget(view);
+ animator.start();*/
+
+ final Handler handler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ float value = (float) msg.obj;
+ if(value>2){
+ @SuppressLint("ResourceType") Animator animator = AnimatorInflater.loadAnimator(context, R.anim.anima_make_none);
+ animator.setTarget(view);
+ animator.start();
+ animator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationEnd(Animator animation, boolean isReverse) {
+ MyLog.i("hideReBound","onAnimationEnd "+animation+" "+isReverse);
+ view.setVisibility(View.GONE);
+ }
+ @Override
+ public void onAnimationStart(Animator animation, boolean isReverse) {}
+ @Override
+ public void onAnimationStart(Animator animator) {
+ }
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ MyLog.i("hideReBound","onAnimationEnd "+animator);
+ view.setVisibility(View.GONE);
+ }
+ @Override
+ public void onAnimationCancel(Animator animator) {}
+ @Override
+ public void onAnimationRepeat(Animator animator) { }
+ });
+ hideAnimaInSitu(view);
+ }else {
+ value = 1f + (value);
+ view.setScaleX(value);
+ view.setScaleY(value);
+ }
+ }
+ };
+ new Thread(){
+ @Override
+ public void run() {
+ try {
+ int sleep = 10;
+ for(int i =0 ; i < 100 ; i+=sleep){
+ sleep(sleep);
+ Message msg = new Message();
+ msg.obj = (float)i/100/3;
+ handler.sendMessage(msg);
+ }
+
+ Message msg = new Message();
+ msg.obj = 3f;
+ handler.sendMessage(msg);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ }
+
+ static int time = 0;
+ public static void animaScale(final Context context, final View view, final float x, final float y){
+
+ final Handler handler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ float value = (float) msg.obj;
+ value = 1f + (value);
+ view.setScaleX(value);
+ view.setScaleY(value);
+ }
+ };
+ new Thread(){
+ @Override
+ public void run() {
+ try {
+ int sleep = 10;
+ for(int i =0 ; i < 100 ; i+=sleep){
+ sleep(sleep);
+ Message msg = new Message();
+ msg.obj = (float)i/100/3;
+ handler.sendMessage(msg);
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ }
+
+ /**
+ * 冒泡式拉伸控件
+ * @param view
+ */
+ public static void scaleReBoundX(final View view, final int size){
+ Log.i("","scaleReBound view:"+view);
+ SpringSystem springSystem = SpringSystem.create();
+ final Spring spring = springSystem.createSpring();
+ spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(100,7));//qcTension拉力和qcFriction摩擦力参数
+ spring.addListener(new SimpleSpringListener() {
+ @Override
+ public void onSpringUpdate(Spring spring) {
+ float value = (float) spring.getCurrentValue();
+ float scale = value;
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ }
+ });
+ spring.setEndValue(size);//控件拉伸收缩的倍率
+ }
+
+ public static void scalXAnima(final View view, float from, float to){
+ setAnimator("scaleX",from,to,view,ANIMA_TIME);
+ }
+}
diff --git a/app/src/main/java/com/runt/open/mvvm/util/PhoneUtil.java b/app/src/main/java/com/runt/open/mvvm/util/PhoneUtil.java
new file mode 100644
index 0000000..6c80502
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/util/PhoneUtil.java
@@ -0,0 +1,77 @@
+package com.runt.open.mvvm.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * My father is Object, ites purpose of
+ *
+ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-4-14.
+ */
+public class PhoneUtil {
+ /**
+ * 验证中国大陆手机号是否合法
+ * @return
+ */
+ public static boolean isCNMobileNO(String mobile){
+ if (mobile.length() != 11)
+ {
+ return false;
+ }else{
+ /**
+ * 移动号段正则表达式
+ */
+ String pat1 = "^((13[4-9])|(147)|(15[0-2,7-9])|(178)|(18[2-4,7-8]))\\d{8}|(1705)\\d{7}$";
+ /**
+ * 联通号段正则表达式
+ */
+ String pat2 = "^((13[0-2])|(145)|(15[5-6])|(176)|(18[5,6]))\\d{8}|(1709)\\d{7}$";
+ /**
+ * 电信号段正则表达式
+ */
+ String pat3 = "^((133)|(153)|(177)|(18[0,1,9])|(149))\\d{8}$";
+ /**
+ * 虚拟运营商正则表达式
+ */
+ String pat4 = "^((170))\\d{8}|(1718)|(1719)\\d{7}$";
+
+ Pattern pattern1 = Pattern.compile(pat1);
+ Matcher match1 = pattern1.matcher(mobile);
+ boolean isMatch1 = match1.matches();
+ if(isMatch1){
+ return true;
+ }
+ Pattern pattern2 = Pattern.compile(pat2);
+ Matcher match2 = pattern2.matcher(mobile);
+ boolean isMatch2 = match2.matches();
+ if(isMatch2){
+ return true;
+ }
+ Pattern pattern3 = Pattern.compile(pat3);
+ Matcher match3 = pattern3.matcher(mobile);
+ boolean isMatch3 = match3.matches();
+ if(isMatch3){
+ return true;
+ }
+ Pattern pattern4 = Pattern.compile(pat4);
+ Matcher match4 = pattern4.matcher(mobile);
+ boolean isMatch4 = match4.matches();
+ if(isMatch4){
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public static boolean isMobileNO( String phone) {
+ //china phone
+ String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";
+ if (phone.length() != 11) {
+ return false;
+ } else {
+ Pattern p = Pattern.compile(regex);
+ Matcher m = p.matcher(phone);
+ return m.matches();
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/runt/open/mvvm/util/PreferencesUtils.java b/app/src/main/java/com/runt/open/mvvm/util/PreferencesUtils.java
new file mode 100644
index 0000000..235dabd
--- /dev/null
+++ b/app/src/main/java/com/runt/open/mvvm/util/PreferencesUtils.java
@@ -0,0 +1,352 @@
+package com.runt.open.mvvm.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import androidx.collection.ArraySet;
+
+import java.util.Set;
+
+/**
+ * PreferencesUtils, easy to get or put data
+ * <ul>
+ * <strong>Preference Name</strong>
+ * <li>you can change preference name by {@link #PREFERENCE_NAME}</li>
+ * </ul>
+ * <ul>
+ * <strong>Put Value</strong>
+ * </ul>
+ *
+ * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-3-6
+ */
+public class PreferencesUtils {
+
+ public static final String PREFERENCE_NAME="zipper";
+ public static final String PROJECT = "project";
+ public static final String USER = "user";
+ public static final String VISITOR = "visitor";
+
+ private PreferencesUtils() {
+ throw new AssertionError();
+ }
+
+ public static boolean clearData(Context context, String keyShared){
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ return settings.edit().clear().commit();
+ }
+
+
+ public static boolean clearData(Context context, String key, String keyShared){
+ putString(context,key,null,keyShared);
+ return true;
+ }
+
+
+
+ /**
+ * remove key preferences
+ *
+ * @param context
+ * @param key The name of the preference to modify
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static void removeKey(Context context, String key, String keyShared){
+
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.remove(key);
+ }
+
+ /**
+ * remove value preferences
+ *
+ * @param context
+ * @param value The name of the preference to modify
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static void removeValue(Context context, String value, String keyShared){
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.remove(value);
+ }
+
+
+ /**
+ * put string preferences
+ *
+ * @param context
+ * @param key The name of the preference to modify
+ * @param value The new value for the preference
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static boolean putString(Context context, String key, String value, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putString(key, value);
+ return editor.commit();
+ }
+
+ /**
+ * get string preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @return The preference value if it exists, or null. Throws ClassCastException if there is a preference with this
+ * name that is not a string
+ * @see #getString(Context, String, String)
+ */
+ public static String getString(Context context, String key, String keyShared) {
+ return getString(context, key, null,keyShared);
+ }
+
+ /**
+ * get string preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @param defaultValue Value to return if this preference does not exist
+ * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
+ * this name that is not a string
+ */
+ public static String getString(Context context, String key, String defaultValue, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ return settings.getString(key, defaultValue);
+ }
+
+ /**
+ * put int preferences
+ *
+ * @param context
+ * @param key The name of the preference to modify
+ * @param value The new value for the preference
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static boolean putInt(Context context, String key, int value, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putInt(key, value);
+ return editor.commit();
+ }
+
+ /**
+ * get int preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @return The preference value if it exists, or -1. Throws ClassCastException if there is a preference with this
+ * name that is not a int
+ */
+ public static int getInt(Context context, String key, String keyShared) {
+ return getInt(context, key, -1,keyShared);
+ }
+
+ /**
+ * get int preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @param defaultValue Value to return if this preference does not exist
+ * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
+ * this name that is not a int
+ */
+ public static int getInt(Context context, String key, int defaultValue, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ try {
+ return settings.getInt(key, defaultValue);
+ }catch (ClassCastException e){
+ try {
+ return Integer.parseInt(settings.getString(key,defaultValue+""));
+ }catch (NumberFormatException en){
+ return defaultValue;
+ }
+ }
+ }
+
+ /**
+ * put long preferences
+ *
+ * @param context
+ * @param key The name of the preference to modify
+ * @param value The new value for the preference
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static boolean putLong(Context context, String key, long value, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putLong(key, value);
+ return editor.commit();
+ }
+
+ /**
+ * get long preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @return The preference value if it exists, or -1. Throws ClassCastException if there is a preference with this
+ * name that is not a long
+ */
+ public static long getLong(Context context, String key, String keyShared) {
+ return getLong(context, key, -1,keyShared);
+ }
+
+ /**
+ * get long preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @param defaultValue Value to return if this preference does not exist
+ * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
+ * this name that is not a long
+ */
+ public static long getLong(Context context, String key, long defaultValue, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ try {
+ return settings.getLong(key, defaultValue);
+ }catch (ClassCastException e){
+ try {
+ return Long.parseLong(settings.getString(key,defaultValue+""));
+ }catch (NumberFormatException en){
+ return defaultValue;
+ }
+ }
+ }
+
+ /**
+ * put float preferences
+ *
+ * @param context
+ * @param key The name of the preference to modify
+ * @param value The new value for the preference
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static boolean putFloat(Context context, String key, float value, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putFloat(key, value);
+ return editor.commit();
+ }
+
+ /**
+ * get float preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @return The preference value if it exists, or -1. Throws ClassCastException if there is a preference with this
+ * name that is not a float
+ */
+ public static float getFloat(Context context, String key, String keyShared) {
+ return getFloat(context, key, -1,keyShared);
+ }
+
+ /**
+ * get float preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @param defaultValue Value to return if this preference does not exist
+ * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
+ * this name that is not a float
+ */
+ public static float getFloat(Context context, String key, float defaultValue, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ try {
+ return settings.getFloat(key, defaultValue);
+ }catch (ClassCastException e){
+ try {
+ return Float.parseFloat(settings.getString(key,defaultValue+""));
+ }catch (NumberFormatException en){
+ return defaultValue;
+ }
+ }
+ }
+
+ /**
+ * put boolean preferences
+ *
+ * @param context
+ * @param key The name of the preference to modify
+ * @param value The new value for the preference
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static boolean putBoolean(Context context, String key, boolean value, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putBoolean(key, value);
+ return editor.commit();
+ }
+
+ /**
+ * get boolean preferences, default is false
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @return The preference value if it exists, or false. Throws ClassCastException if there is a preference with this
+ * name that is not a boolean
+ */
+ public static boolean getBoolean(Context context, String key, String keyShared) {
+ return getBoolean(context, key, false,keyShared);
+ }
+
+ /**
+ * get boolean preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @param defaultValue Value to return if this preference does not exist
+ * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
+ * this name that is not a boolean
+ */
+ public static boolean getBoolean(Context context, String key, boolean defaultValue, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ try {
+ return settings.getBoolean(key, defaultValue);
+ }catch (ClassCastException e){
+ try {
+ return Boolean.parseBoolean(settings.getString(key,defaultValue+""));
+ }catch (NumberFormatException en){
+ return defaultValue;
+ }
+ }
+ }
+
+ /**
+ * put boolean preferences
+ *
+ * @param context
+ * @param key The name of the preference to modify
+ * @param value The new value for the preference , the value of set ,canot be the other class out of java collection
+ * @return True if the new values were successfully written to persistent storage.
+ */
+ public static boolean putStringSet(Context context, String key, Set value, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putStringSet(key, value);
+ return editor.commit();
+ }
+
+ /**
+ * get boolean preferences, default is false
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @return The preference value if it exists, or false. Throws ClassCastException if there is a preference with this
+ * name that is not a boolean 获取出来的值最终被转换为hashset类型
+ */
+ public static Set getStringSet(Context context, String key, String keyShared) {
+ return getStringSet(context, key,new ArraySet(),keyShared);
+ }
+
+ /**
+ * get boolean preferences
+ *
+ * @param context
+ * @param key The name of the preference to retrieve
+ * @param defaultValue Value to return if this preference does not exist
+ * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
+ * this name that is not a boolean 获取出来的值最终被转换为hashset类型
+ */
+ public static Set getStringSet(Context context, String key, Set defaultValue, String keyShared) {
+ SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE);
+ return settings.getStringSet(key, defaultValue);
+ }
+}
diff --git a/app/src/main/res/color/btn_txt_normal.xml b/app/src/main/res/color/btn_txt_normal.xml
new file mode 100644
index 0000000..05ff6ac
--- /dev/null
+++ b/app/src/main/res/color/btn_txt_normal.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:tools="http://schemas.android.com/tools"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ tools:ignore="MissingDefaultResource">
+ <item android:state_enabled="false" android:color="@color/txt_enable"/> <!-- pressed -->
+ <item android:state_pressed="true" android:color="@color/txt_cusor_color"/> <!-- pressed -->
+ <item android:state_focused="true" android:color="@color/txt_hint"/> <!-- focused -->
+ <item android:color="@color/white"/> <!-- default -->
+</selector>
\ 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..9cc3693
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.runt.open.mvvm.widgets.TitleBarView
+ android:id="@+id/title_bar"
+ style="@style/titlebar"
+ app:leftDrawable="@mipmap/ic_arrow_back_black_24dp"
+ app:titleText="登录"
+ tools:ignore="MissingConstraints" />
+
+
+ <ImageView
+ android:id="@+id/img_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="50dp"
+ android:src="@mipmap/app_icon"
+ android:adjustViewBounds="true"
+ app:layout_constraintTop_toBottomOf="@id/title_bar"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ />
+
+ <com.runt.open.mvvm.widgets.ClearEditText
+ android:id="@+id/edit_phone"
+ style="@style/login_edit"
+ android:hint="@string/input_phone"
+ android:inputType="phone"
+ app:layout_constraintTop_toBottomOf="@id/img_icon"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ />
+
+
+ <com.runt.open.mvvm.widgets.ClearEditText
+ android:id="@+id/edit_verify_code"
+ style="@style/login_edit"
+ android:hint="@string/input_verify_code"
+ android:inputType="number"
+ app:layout_constraintTop_toBottomOf="@id/edit_phone"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"/>
+
+
+ <TextView
+ android:id="@+id/txt_get_verify"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/link"
+ android:layout_marginRight="@dimen/default_margin_lr"
+ android:text="@string/get_verify_code"
+ android:gravity="center"
+ app:layout_constraintTop_toTopOf="@id/edit_verify_code"
+ app:layout_constraintRight_toRightOf="@id/edit_verify_code"
+ app:layout_constraintBottom_toBottomOf="@id/edit_verify_code"/>
+
+
+ <com.runt.open.mvvm.widgets.ClearEditText
+ android:id="@+id/edit_pass"
+ style="@style/login_edit"
+ android:inputType="textPassword"
+ android:hint="@string/input_pass"
+ app:layout_constraintTop_toBottomOf="@id/edit_verify_code"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent" />
+
+
+ <com.runt.open.mvvm.widgets.ClearEditText
+ android:id="@+id/edit_pass_repeat"
+ style="@style/login_edit"
+ android:hint="@string/str_input_repeat"
+ android:inputType="textPassword"
+ app:layout_constraintTop_toBottomOf="@id/edit_pass"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"/>
+
+
+ <TextView
+ android:id="@+id/txt_forgot"
+ style="@style/login_link"
+ android:text="@string/forgot_pass"
+ app:layout_constraintTop_toBottomOf="@id/edit_pass_repeat"
+ app:layout_constraintLeft_toLeftOf="parent" />
+ <TextView
+ android:id="@+id/txt_register"
+ style="@style/login_link"
+ android:text="@string/register"
+ app:layout_constraintTop_toBottomOf="@id/edit_pass_repeat"
+ app:layout_constraintLeft_toRightOf="@id/txt_forgot"
+ app:layout_constraintRight_toLeftOf="@id/txt_login" />
+ <TextView
+ android:id="@+id/txt_login"
+ style="@style/login_link"
+ android:text="@string/login"
+ app:layout_constraintTop_toBottomOf="@id/edit_pass_repeat"
+ app:layout_constraintRight_toRightOf="parent" />
+
+ <androidx.appcompat.widget.AppCompatCheckBox
+ android:id="@+id/checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/default_margin_lr"
+ android:layout_marginBottom="@dimen/default_margin_lr"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/button"/>
+ <TextView
+ android:id="@+id/txt_privacy"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/default_margin_td"
+ android:paddingBottom="@dimen/default_margin_td"
+ android:paddingRight="@dimen/default_margin_lr"
+ android:background="@color/white"
+ android:textColor="@color/link"
+ android:text=" 我已阅读并同意《隐私条款》"
+ app:layout_constraintLeft_toRightOf="@id/checkbox"
+ app:layout_constraintTop_toTopOf="@id/checkbox"
+ app:layout_constraintBottom_toBottomOf="@id/checkbox"/>
+ <Button
+ android:id="@+id/button"
+ style="@style/btn_normal"
+ android:layout_marginBottom="@dimen/default_margin_lr"
+ android:text="@string/login"
+ android:layout_marginLeft="@dimen/default_margin_lr"
+ android:layout_marginRight="@dimen/default_margin_lr"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"/>
+</androidx.constraintlayout.widget.ConstraintLayout>
+
+
+
diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml
new file mode 100644
index 0000000..c3ad397
--- /dev/null
+++ b/app/src/main/res/layout/activity_web.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <com.runt.open.mvvm.widgets.TitleBarView
+ android:id="@+id/title_bar"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ style="@style/titlebar" />
+
+ <LinearLayout
+ android:id="@+id/lin_progressbar"
+ android:layout_width="match_parent"
+ android:layout_height="2dp"
+ android:background="@drawable/bg_gradient_gray"
+ app:layout_constraintTop_toBottomOf="@id/title_bar"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ android:visibility="gone">
+ <View
+ android:id="@+id/view_progressbar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:animateLayoutChanges="true"
+ android:background="@drawable/bg_gradient_blue"/>
+ </LinearLayout>
+
+ <WebView
+ android:id="@+id/browser"
+ app:layout_constraintTop_toBottomOf="@id/title_bar"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1c9793b..15ac25b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,4 +2,71 @@
<string name="title_home">Home</string>
<string name="title_dashboard">Dashboard</string>
<string name="title_notifications">Notifications</string>
+ <string name="get_verify_code">获取验证码</string>
+ <string name="select_region">选择国家/地区</string>
+ <string name="input_phone">请输入手机号</string>
+ <string name="input_pass">请输入密码</string>
+ <string name="input_verify_code">请输入验证码</string>
+ <string name="input_invite_code">请输入邀请码</string>
+ <string name="forgot_pass">忘记密码?</string>
+ <string name="register">注册</string>
+ <string name="login">登录</string>
+ <string name="msg_login">短信登录</string>
+ <string name="str_input_old">请输入旧密码</string>
+ <string name="str_input_new">请输入新密码</string>
+ <string name="str_input_repeat">请再次输入新密码</string>
+ <string name="str_pass_format_failed">密码要求6-12位数(数字/英文大小写/符号混合)格式</string>
+ <string name="str_cannot_eques_old">新密码不能与旧密码相同</string>
+ <string name="str_new_verify_failed">新密码两次输入不相同</string>
+ <string name="str_edit_pass">修改密码</string>
+ <string name="str_confirm">确认</string>
+ <string name="str_invite">推荐码</string>
+ <string name="str_mine">个人中心</string>
+ <string name="str_setting">设置</string>
+ <string name="str_msg">消息中心</string>
+ <string name="str_version">版本号</string>
+ <string name="str_msg_detail">资讯详情</string>
+ <string name="str_copied">复制成功</string>
+ <string name="str_get_data_failed">获取数据失败</string>
+ <string name="str_phone_format_failed">输入手机格式不正确</string>
+ <string name="login_pass_failed">账号或者密码错误,请重新输入</string>
+ <string name="login_code_failed">验证码有误,请重新输入</string>
+ <string name="comming_soon">敬请期待</string>
+ <string name="notice">通知</string>
+ <string name="save_img">保存图片</string>
+ <string name="copy_url">复制链接</string>
+ <string name="toast_login">请先登录后再操作</string>
+ <string name="registed">账号已经注册了</string>
+ <string name="failed">操作失败</string>
+ <string name="none_account">账号不存在</string>
+ <string name="loading">加载中</string>
+ <string name="register_success">账号注册成功请登录</string>
+ <string name="verify_failed">验证码失效</string>
+ <string name="invite_error">错误的邀请码</string>
+ <string name="update_pass_sucess">密码修改成功</string>
+ <string name="update_pass_failed_old">旧密码错误</string>
+ <string name="update_pass_failed">密码修改失败</string>
+ <string name="login_success">登录成功</string>
+ <string name="login_failed">登录失败</string>
+ <string name="login_failed_pass">密码错误</string>
+ <string name="new_version">新版本更新</string>
+ <string name="str_cancel">取消</string>
+ <string name="logouted">登录失效,请重新登录</string>
+
+ <string name="forgot_update_pwd">点击忘记密码去修改</string>
+ <string name="download">下载</string>
+ <string name="created_at">更新</string>
+ <string name="msg_deleted">消息已被删除</string>
+ <string name="logout">退出登录</string>
+ <string name="internet_failed">网络连接失败</string>
+ <string name="str_miner_running">正在挖矿</string>
+ <string name="str_apply">申请</string>
+ <string name="str_permission">需要获取文件存储权限才能查看</string>
+ <string name="str_wait">敬请期待</string>
+ <string name="str_node_l">您当前为三级节点</string>
+ <string name="str_email">官方邮箱:</string>
+ <string name="str_website">官方网站:</string>
+ <string name="str_restart">重启APP</string>
+ <string name="str_success">成功</string>
+ <string name="str_no_up">暂无更新</string>
</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index db5c358..4884702 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -63,4 +63,48 @@
<style name="TransparentDialog" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@color/transparent</item>
</style>
+
+ <style name="titlebar">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">?attr/actionBarSize</item>
+ <item name="android:background">@color/white</item>
+ <item name="titleTextColor">@color/txt_normal</item>
+ <item name="layout_constraintTop_toTopOf">parent</item>
+ <item name="layout_constraintLeft_toLeftOf">parent</item>
+ <item name="layout_constraintRight_toRightOf">parent</item>
+ <item name="android:paddingLeft">@dimen/default_margin_lr</item>
+ <item name="android:paddingRight">@dimen/default_margin_lr</item>
+ </style>
+
+
+ <style name="btn_normal">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:background">@drawable/btn_circle_blue</item>
+ <item name="android:textColor">@color/btn_txt_normal</item>
+ <item name="android:textSize">@dimen/title_size</item>
+ </style>
+
+ <style name="login_edit">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">@dimen/title_height</item>
+ <item name="android:background">@drawable/bg_circle_default</item>
+ <item name="android:layout_marginTop">@dimen/default_margin_td</item>
+ <item name="android:paddingRight">@dimen/default_margin_lr</item>
+ <item name="android:paddingLeft">@dimen/default_margin_lr</item>
+ <item name="android:singleLine">true</item>
+ <item name="android:gravity">center_vertical</item>
+ <item name="android:layout_marginLeft">@dimen/default_margin_lr</item>
+ <item name="android:layout_marginRight">@dimen/default_margin_lr</item>
+ </style>
+
+ <style name="login_link">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:paddingTop">@dimen/default_margin_td</item>
+ <item name="android:paddingBottom">@dimen/default_margin_td</item>
+ <item name="android:paddingRight">30dp</item>
+ <item name="android:paddingLeft">30dp</item>
+ <item name="android:textColor">@color/link</item>
+ </style>
</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 99e3317..3765728 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -3,7 +3,7 @@
<style name="Theme.OpemMvvm" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/sky</item>
- <item name="colorPrimaryVariant">@color/red</item>
+ <item name="colorPrimaryVariant">@color/blue_sky</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/black_4</item>
@@ -12,6 +12,9 @@
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
+ <!--全局设置文本颜色和大小-->
+ <item name="android:textColor">@color/txt_normal</item>
+ <item name="android:textSize">@dimen/txt_size</item>
</style>
--
Gitblit v1.9.1