Drew 6 jaren geleden
bovenliggende
commit
fb89227591
33 gewijzigde bestanden met toevoegingen van 1204 en 65 verwijderingen
  1. 40 1
      .idea/misc.xml
  2. 6 0
      .idea/vcs.xml
  3. 7 1
      app/build.gradle
  4. 6 3
      app/src/main/AndroidManifest.xml
  5. BIN
      app/src/main/assets/font/roboto_normal.ttf
  6. BIN
      app/src/main/assets/font/source_han_sans_sc_light.otf
  7. BIN
      app/src/main/assets/font/source_han_sans_sc_medium.otf
  8. BIN
      app/src/main/assets/font/source_han_sans_sc_normal.otf
  9. 157 0
      app/src/main/java/com/ht/gate/KeyboardUtil.java
  10. 108 0
      app/src/main/java/com/ht/gate/LoginActivity.java
  11. 0 19
      app/src/main/java/com/ht/gate/MainActivity.java
  12. 86 3
      app/src/main/java/com/ht/gate/UnlockView.java
  13. 27 0
      app/src/main/java/com/ht/gate/activity/MainActivity.java
  14. 453 0
      app/src/main/java/com/ht/gate/view/CustomKeyboardView.java
  15. 5 0
      app/src/main/res/drawable/bg_edit.xml
  16. 5 0
      app/src/main/res/drawable/bg_key.xml
  17. 8 0
      app/src/main/res/drawable/cursor.xml
  18. BIN
      app/src/main/res/font/source_han_sans_sc_medium.otf
  19. 73 0
      app/src/main/res/layout/activity_login.xml
  20. 27 36
      app/src/main/res/layout/activity_main.xml
  21. 7 0
      app/src/main/res/layout/alphabetic_keyboard.xml
  22. BIN
      app/src/main/res/mipmap-xhdpi/icon_cap.png
  23. BIN
      app/src/main/res/mipmap-xhdpi/icon_del.png
  24. BIN
      app/src/main/res/mipmap-xxhdpi/icon_cap.png
  25. BIN
      app/src/main/res/mipmap-xxhdpi/icon_del.png
  26. BIN
      app/src/main/res/mipmap-xxhdpi/icon_setting.png
  27. BIN
      app/src/main/res/mipmap-xxxhdpi/icon_cap.png
  28. BIN
      app/src/main/res/mipmap-xxxhdpi/icon_del.png
  29. BIN
      app/src/main/res/mipmap-xxxhdpi/icon_setting.png
  30. 10 0
      app/src/main/res/values/attr.xml
  31. 1 1
      app/src/main/res/values/colors.xml
  32. 1 1
      app/src/main/res/values/styles.xml
  33. 177 0
      app/src/main/res/xml/custom_keyboard.xml

+ 40 - 1
.idea/misc.xml

@@ -1,6 +1,45 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
+    <option name="myDefaultNotNull" value="androidx.annotation.RecentlyNonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="12">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
+          <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+          <item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
+          <item index="6" class="java.lang.String" itemvalue="android.annotation.Nullable" />
+          <item index="7" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
+          <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
+          <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
+          <item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
+          <item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="11">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+          <item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
+          <item index="5" class="java.lang.String" itemvalue="android.annotation.NonNull" />
+          <item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
+          <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
+          <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
+          <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
+          <item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
   <component name="ProjectType">

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 7 - 1
app/build.gradle

@@ -17,6 +17,10 @@ android {
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
 }
 
 dependencies {
@@ -24,7 +28,9 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.1.0'
     implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
     testImplementation 'junit:junit:4.12'
-    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
     implementation "android.arch.lifecycle:extensions:1.1.3"
+    implementation 'com.jakewharton:butterknife:10.2.0'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.0'
 }

+ 6 - 3
app/src/main/AndroidManifest.xml

@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="com.ht.gate">
 
     <application
@@ -7,9 +8,11 @@
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:roundIcon="@mipmap/ic_launcher_round"
-        android:supportsRtl="true"
-        android:theme="@style/AppTheme">
-        <activity android:name=".MainActivity">
+        android:supportsRtl="false"
+        android:theme="@style/AppTheme"
+        tools:ignore="GoogleAppIndexingWarning">
+        <activity android:name=".activity.MainActivity"></activity>
+        <activity android:name=".LoginActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 

BIN
app/src/main/assets/font/roboto_normal.ttf


BIN
app/src/main/assets/font/source_han_sans_sc_light.otf


BIN
app/src/main/assets/font/source_han_sans_sc_medium.otf


BIN
app/src/main/assets/font/source_han_sans_sc_normal.otf


+ 157 - 0
app/src/main/java/com/ht/gate/KeyboardUtil.java

@@ -0,0 +1,157 @@
+package com.ht.gate;
+
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.text.Editable;
+import android.text.InputType;
+import android.view.View;
+import android.widget.EditText;
+
+@SuppressWarnings("deprecation")
+public class KeyboardUtil {
+    private View keyboardParentView;
+    private KeyboardView keyboardView;
+    private EditText editText;
+    private Keyboard keyboard;// 键盘
+
+    public KeyboardUtil(View keyboardParentView, KeyboardView keyboardView, EditText editText) {
+        this.keyboardParentView = keyboardParentView;
+        this.keyboardView = keyboardView;
+        this.editText = editText;
+
+        this.keyboard = new Keyboard(editText.getContext(), R.xml.custom_keyboard);
+        this.editText.setInputType(InputType.TYPE_NULL);
+        this.keyboardView.setOnKeyboardActionListener(listener);
+        this.keyboardView.setKeyboard(keyboard);
+        this.keyboardView.setEnabled(true);
+        this.keyboardView.setPreviewEnabled(false);
+    }
+
+    private KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() {
+
+        @Override
+        public void swipeUp() {
+        }
+
+        @Override
+        public void swipeRight() {
+
+        }
+
+        @Override
+        public void swipeLeft() {
+        }
+
+        @Override
+        public void swipeDown() {
+        }
+
+        @Override
+        public void onText(CharSequence text) {
+        }
+
+        @Override
+        public void onRelease(int primaryCode) {
+        }
+
+        @Override
+        public void onPress(int primaryCode) {
+        }
+
+        @Override
+        public void onKey(int primaryCode, int[] keyCodes) {
+            Editable editable = editText.getText();
+            int start = editText.getSelectionStart();
+            switch (primaryCode) {
+                case Keyboard.KEYCODE_DELETE:
+                    if (editable != null && editable.length() > 0) {
+                        if (start > 0) {
+                            editable.delete(start - 1, start);
+                        }
+                    }
+                    break;
+                case Keyboard.KEYCODE_DONE:
+                    if (runnable != null) {
+                        keyboardView.postDelayed(runnable, 200);
+                    } else {
+                        if (keyboardParentView != null) {
+                            keyboardParentView.setVisibility(View.GONE);
+                        } else {
+                            keyboardView.setVisibility(View.GONE);
+                        }
+                    }
+                    break;
+                case 73:
+                case 79:
+                    break;
+                default:
+                    editable.insert(start, Character.toString((char) primaryCode));
+                    break;
+            }
+        }
+    };
+
+    private Runnable runnable = new Runnable() {
+        @Override
+        public void run() {
+            if (keyboardParentView != null) {
+                if (keyboardParentView.getVisibility() == View.VISIBLE) {
+                    keyboardParentView.setVisibility(View.GONE);
+                }
+            } else {
+                if (keyboardView != null) {
+                    if (keyboardView.getVisibility() == View.VISIBLE) {
+                        keyboardView.setVisibility(View.GONE);
+                    }
+                }
+            }
+        }
+    };
+
+    public void showKeyboard() {
+        if (keyboardParentView != null) {
+            int visibility = keyboardParentView.getVisibility();
+            if (visibility == View.GONE || visibility == View.INVISIBLE) {
+                keyboardParentView.setVisibility(View.VISIBLE);
+            }
+        } else {
+            if (keyboardView == null) {
+                return;
+            }
+            int visibility = keyboardView.getVisibility();
+            if (visibility == View.GONE || visibility == View.INVISIBLE) {
+                keyboardView.setVisibility(View.VISIBLE);
+            }
+        }
+    }
+
+    public void hideKeyboard() {
+        if (keyboardParentView != null) {
+            int visibility = keyboardParentView.getVisibility();
+            if (visibility == View.VISIBLE) {
+                keyboardParentView.setVisibility(View.GONE);
+            }
+        } else {
+            if (keyboardView == null) {
+                return;
+            }
+            int visibility = keyboardView.getVisibility();
+            if (visibility == View.VISIBLE) {
+                keyboardView.setVisibility(View.GONE);
+            }
+        }
+    }
+
+    public int getKeyboardVisibility() {
+        int visibility = View.GONE;
+        if (keyboardParentView != null) {
+            visibility = keyboardParentView.getVisibility();
+
+        } else {
+            if (keyboardView != null) {
+                visibility = keyboardView.getVisibility();
+            }
+        }
+        return visibility;
+    }
+}

+ 108 - 0
app/src/main/java/com/ht/gate/LoginActivity.java

@@ -0,0 +1,108 @@
+package com.ht.gate;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.Editable;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.ht.gate.activity.MainActivity;
+import com.ht.gate.view.CustomKeyboardView;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+public class LoginActivity extends AppCompatActivity {
+
+    @BindView(R.id.parent_layout)
+    ConstraintLayout parentLayout;
+    @BindView(R.id.keyboard_view)
+    CustomKeyboardView keyboardView;
+    @BindView(R.id.et)
+    EditText et;
+    @BindView(R.id.unlock_view)
+    UnlockView unlockView;
+
+    private KeyboardUtil keyboardUtil;
+
+    @SuppressLint("ClickableViewAccessibility")
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_login);
+        ButterKnife.bind(this);
+
+        unlockView.setUnlockListener(() -> {
+            unlockView.setVisibility(View.GONE);
+            et.setVisibility(View.VISIBLE);
+            keyboardView.show();
+        });
+        et.setOnTouchListener((v, event) -> {
+            if (event.getAction() == MotionEvent.ACTION_UP) {
+                if (keyboardView.getVisibility() == View.GONE) {
+                    keyboardView.show();
+                }
+            }
+            return true;
+        });
+        keyboardView.setKeyboardActionListener(new CustomKeyboardView.OnKeyboardActionListener() {
+            @Override
+            public void onPress(int primaryCode) {
+
+            }
+
+            @Override
+            public void onRelease(int primaryCode) {
+
+            }
+
+            @Override
+            public void onKey(int primaryCode, int[] keyCodes) {
+                Log.d("onKey", primaryCode + "");
+                Editable editable = et.getText();
+                int start = et.getSelectionStart();
+                switch (primaryCode) {
+                    case CustomKeyboardView.KEYCODE_CANCEL:
+                        et.setVisibility(View.GONE);
+                        unlockView.setVisibility(View.VISIBLE);
+                        break;
+                    case CustomKeyboardView.KEYCODE_DONE:
+                        startActivity(new Intent(LoginActivity.this, MainActivity.class));
+                        break;
+                    case CustomKeyboardView.KEYCODE_DELETE:
+                        if (editable != null && editable.length() > 0) {
+                            if (start > 0) {
+                                editable.delete(start - 1, start);
+                            }
+                        }
+                        break;
+                    default:
+                        editable.insert(start, Character.toString((char) primaryCode));
+                        break;
+                }
+            }
+
+            @Override
+            public void onText(CharSequence text) {
+
+            }
+        });
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        View decorView = getWindow().getDecorView();
+        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_IMMERSIVE;
+        decorView.setSystemUiVisibility(uiOptions);
+    }
+}

+ 0 - 19
app/src/main/java/com/ht/gate/MainActivity.java

@@ -1,19 +0,0 @@
-package com.ht.gate;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import android.os.Bundle;
-import android.util.DisplayMetrics;
-
-public class MainActivity extends AppCompatActivity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_main);
-
-        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
-        float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
-        float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
-    }
-}

+ 86 - 3
app/src/main/java/com/ht/gate/UnlockView.java

@@ -1,16 +1,21 @@
 package com.ht.gate;
 
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.DrawFilter;
+import android.graphics.LinearGradient;
 import android.graphics.Paint;
 import android.graphics.PaintFlagsDrawFilter;
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.Typeface;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.TypedValue;
@@ -22,6 +27,9 @@ import androidx.annotation.Nullable;
 public class UnlockView extends View {
 
     private Paint borderPaint;
+    private Paint linePaint;
+    private Paint textPaint;
+    private Shader lineShader;
     private Path borderPath;
     private float borderWidth;
     private Bitmap bmUnlock;
@@ -31,7 +39,22 @@ public class UnlockView extends View {
     private float lastX;
     private Rect src;
     private RectF dst;
-    private DrawFilter pfdf;
+    private DrawFilter drawFilter;
+    private Typeface source_han_sans_sc_normal;
+    private Typeface source_han_sans_sc_light;
+
+    private String hint;
+
+    private UnlockListener unlockListener;
+    private boolean unlocked;
+
+    public interface UnlockListener {
+        void onUnlock();
+    }
+
+    public void setUnlockListener(UnlockListener unlockListener) {
+        this.unlockListener = unlockListener;
+    }
 
     public UnlockView(Context context) {
         this(context, null);
@@ -47,6 +70,8 @@ public class UnlockView extends View {
 
     public UnlockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        source_han_sans_sc_normal = Typeface.createFromAsset(this.getContext().getAssets(), "font/source_han_sans_sc_normal.otf");
+        source_han_sans_sc_light = Typeface.createFromAsset(this.getContext().getAssets(), "font/source_han_sans_sc_light.otf");
         borderPaint = new Paint();
         borderPaint.setAntiAlias(true);
         borderPaint.setColor(Color.WHITE);
@@ -59,7 +84,27 @@ public class UnlockView extends View {
         bmUnlock = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_unlock);
         src = new Rect(0, 0, bmUnlock.getWidth(), bmUnlock.getHeight());
         dst = new RectF();
-        pfdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+
+        drawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+
+        linePaint = new Paint();
+        linePaint.setAntiAlias(true);
+        linePaint.setStrokeCap(Paint.Cap.ROUND);
+
+        textPaint = new Paint();
+        textPaint.setAntiAlias(true);
+        textPaint.setColor(Color.WHITE);
+        textPaint.setTextSize(sp2px(25));
+        textPaint.setStyle(Paint.Style.FILL);
+        textPaint.setTypeface(source_han_sans_sc_light);
+
+        TypedArray t = getContext().obtainStyledAttributes(attrs,
+                R.styleable.UnlockView);
+        hint = t.getString(R.styleable.UnlockView_hint);
+        if (TextUtils.isEmpty(hint)) {
+            hint = "滑动解锁";
+        }
+        t.recycle();
     }
 
     @Override
@@ -69,7 +114,7 @@ public class UnlockView extends View {
 
     @Override
     protected void onDraw(Canvas canvas) {
-        canvas.setDrawFilter(pfdf);
+        canvas.setDrawFilter(drawFilter);
         float width = getWidth();
         float height = getHeight();
         float d = (height - borderWidth);
@@ -84,11 +129,22 @@ public class UnlockView extends View {
 
         float size = height - padding * 2;
         int dd = (int) Math.max(0, Math.min(distance, getWidth() - padding * 2 - size));
+
+        linePaint.setStrokeWidth(height - padding * 2);
+        lineShader = new LinearGradient(0, 0, width, 0,
+                new int[]{Color.argb(0, 255, 255, 255), Color.argb(30, 255, 255, 255), Color.argb(117, 255, 255, 255), Color.argb(255, 255, 255, 255)},
+                new float[]{0, 0.19f, 0.42f, 1}, Shader.TileMode.CLAMP);
+        linePaint.setShader(lineShader);
+        canvas.drawLine(r, height / 2, r + dd, height / 2, linePaint);
+
+        drawCenterText(canvas, textPaint, hint);
+
         dst.left = (int) padding + dd;
         dst.top = (int) padding;
         dst.right = (int) (padding + size + dd);
         dst.bottom = (int) (padding + size);
         canvas.drawBitmap(bmUnlock, src, dst, null);
+
     }
 
     @Override
@@ -101,13 +157,22 @@ public class UnlockView extends View {
                 }
                 break;
             case MotionEvent.ACTION_UP:
+                distance = 0;
                 down = false;
+                unlocked = false;
+                postInvalidate();
                 break;
             case MotionEvent.ACTION_MOVE:
                 if (down) {
                     distance += event.getX() - lastX;
                     lastX = event.getX();
                     postInvalidate();
+                    if (distance >= getWidth() - padding * 2 - (getHeight() - padding * 2) && !unlocked) {
+                        unlocked = true;
+                        if (unlockListener != null) {
+                            unlockListener.onUnlock();
+                        }
+                    }
                 }
                 break;
         }
@@ -122,4 +187,22 @@ public class UnlockView extends View {
             bmUnlock = null;
         }
     }
+
+    private void drawCenterText(Canvas canvas, Paint paint, String text) {
+        // 文本宽
+        float textWidth = paint.measureText(text);
+        // 文本baseline在y轴方向的位置
+        float baseLineY = Math.abs(paint.ascent() + paint.descent()) / 2 + getHeight() / 2f;
+        canvas.drawText(text, getWidth() / 2f - textWidth / 2, baseLineY, paint);
+    }
+
+    public int sp2px(float sp) {
+        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
+                getContext().getResources().getDisplayMetrics());
+    }
+
+    public int dp2px(float dp) {
+        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
+                getContext().getResources().getDisplayMetrics());
+    }
 }

+ 27 - 0
app/src/main/java/com/ht/gate/activity/MainActivity.java

@@ -0,0 +1,27 @@
+package com.ht.gate.activity;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.os.Bundle;
+import android.view.View;
+
+import com.ht.gate.R;
+
+public class MainActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        View decorView = getWindow().getDecorView();
+        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_IMMERSIVE;
+        decorView.setSystemUiVisibility(uiOptions);
+    }
+}

+ 453 - 0
app/src/main/java/com/ht/gate/view/CustomKeyboardView.java

@@ -0,0 +1,453 @@
+package com.ht.gate.view;
+
+import android.animation.Animator;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.DrawFilter;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.os.Handler;
+import android.os.Message;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Animation;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.TranslateAnimation;
+
+import androidx.annotation.Nullable;
+
+import com.ht.gate.R;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SuppressWarnings("deprecation")
+public class CustomKeyboardView extends View {
+
+    public interface OnKeyboardActionListener {
+        void onPress(int primaryCode);
+
+        void onRelease(int primaryCode);
+
+        void onKey(int primaryCode, int[] keyCodes);
+
+        void onText(CharSequence text);
+    }
+
+    public static final int KEYCODE_CANCEL = -3;
+    public static final int KEYCODE_DONE = -4;
+    public static final int KEYCODE_DELETE = -5;
+
+    private static final int NOT_A_KEY = -1;
+    private static final int[] KEY_DELETE = {Keyboard.KEYCODE_DELETE};
+    private static int MAX_NEARBY_KEYS = 12;
+    private static final int REPEAT_INTERVAL = 50; // ~20 keys per second
+    private static final int REPEAT_START_DELAY = 400;
+    private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
+
+    private int[] mDistances = new int[MAX_NEARBY_KEYS];
+    private int mLastSentIndex;
+    private int mTapCount;
+    private long mLastTapTime;
+    private static final int MULTITAP_INTERVAL = 800; // milliseconds
+    private StringBuilder mPreviewLabel = new StringBuilder(1);
+
+    private int mVerticalCorrection;
+    private int mProximityThreshold;
+    private boolean mProximityCorrectOn;
+
+    private int mOldPointerCount = 1;
+    private float mOldPointerX;
+    private float mOldPointerY;
+
+    private int mLastX;
+    private int mLastY;
+    private int mStartX;
+    private int mStartY;
+
+    private long mDownTime;
+    private long mLastMoveTime;
+    private int mLastKey;
+    private int mLastCodeX;
+    private int mLastCodeY;
+    private int mCurrentKey = NOT_A_KEY;
+    private int mDownKey = NOT_A_KEY;
+    private long mLastKeyTime;
+    private long mCurrentKeyTime;
+
+    private static final int MSG_SHOW_PREVIEW = 1;
+    private static final int MSG_REMOVE_PREVIEW = 2;
+    private static final int MSG_REPEAT = 3;
+    private static final int MSG_LONGPRESS = 4;
+
+
+    private Keyboard mKeyboard;
+    private Keyboard.Key[] mKeys;
+    private Paint mPaint;
+    private Paint mBitmapPaint;
+    private int mPaddingH;
+    private int mPaddingV;
+    private int radius;
+    private int mKeyOffsetX;
+    private int mKeyOffsetY;
+    private int mLegendHeight;
+    private int mLegendBtnWidth;
+    private int mBtnCancelColor = 0x80ffffff;
+    private int mBtnConfirmColor = 0xFFE4BF85;
+    private int mKeyBackgroundColor = 0xff444857;
+    private int mLegendBackground = 0xFF2B2E3A;
+    private Typeface source_han_sans_sc_normal;
+    private Typeface source_han_sans_sc_medium;
+    private Typeface roboto_normal;
+    private DrawFilter filter;
+    private ColorMatrixColorFilter colorFilterWhite;
+    private ColorMatrixColorFilter colorFilterBlack;
+
+    private OnKeyboardActionListener mKeyboardActionListener;
+    private String mLegend;
+
+    private boolean cap;
+
+    Handler mHandler;
+
+    public void setKeyboardActionListener(OnKeyboardActionListener mKeyboardActionListener) {
+        this.mKeyboardActionListener = mKeyboardActionListener;
+    }
+
+    public void setCap(boolean cap) {
+        this.cap = cap;
+    }
+
+    public void show() {
+        int width = getWidth();
+        if (width == 0) {
+            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+            width = (int) (displayMetrics.widthPixels / displayMetrics.density);
+        }
+
+        measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+
+        final int targetHeight = getMeasuredHeight();
+
+        setVisibility(VISIBLE);
+        TranslateAnimation animate = new TranslateAnimation(0, 0, getHeight() <= 0 ? targetHeight : getHeight(), 0);
+        animate.setDuration(200);
+        animate.setFillAfter(true);
+        animate.setInterpolator(new AccelerateDecelerateInterpolator());
+        startAnimation(animate);
+    }
+
+    public void hide() {
+        TranslateAnimation animate = new TranslateAnimation(0, 0, 0, getHeight());
+        animate.setDuration(200);
+        animate.setFillAfter(true);
+        animate.setAnimationListener(new Animation.AnimationListener() {
+            @Override
+            public void onAnimationStart(Animation animation) {
+
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation) {
+                setVisibility(GONE);
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation) {
+
+            }
+        });
+        startAnimation(animate);
+    }
+
+    public CustomKeyboardView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CustomKeyboardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        setKeyboard(new Keyboard(getContext(), R.xml.custom_keyboard));
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+
+        mPaddingH = 0;
+        mPaddingV = dp2px(12);
+        radius = dp2px(2);
+        mLegendHeight = dp2px(65);
+        mLegendBtnWidth = dp2px(75);
+        mKeyOffsetX = 0;
+        mKeyOffsetY = dp2px(12);
+        source_han_sans_sc_normal = Typeface.createFromAsset(this.getContext().getAssets(), "font/source_han_sans_sc_normal.otf");
+        source_han_sans_sc_medium = Typeface.createFromAsset(this.getContext().getAssets(), "font/source_han_sans_sc_medium.otf");
+        roboto_normal = Typeface.createFromAsset(this.getContext().getAssets(), "font/roboto_normal.ttf");
+        filter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+
+        mBitmapPaint = new Paint();
+        mBitmapPaint.setAntiAlias(true);
+        mBitmapPaint.setDither(true);
+        colorFilterWhite = new ColorMatrixColorFilter(new ColorMatrix(new float[]{
+                0, 0, 0, 0, 255,
+                0, 0, 0, 0, 255,
+                0, 0, 0, 0, 255,
+                0, 0, 0, 1, 0,
+        }));
+        colorFilterBlack = new ColorMatrixColorFilter(new ColorMatrix(new float[]{
+                0, 0, 0, 0, 68,
+                0, 0, 0, 0, 72,
+                0, 0, 0, 0, 87,
+                0, 0, 0, 1, 0,
+        }));
+
+        TypedArray t = getContext().obtainStyledAttributes(attrs,
+                R.styleable.CustomKeyboardView);
+        mLegend = t.getString(R.styleable.CustomKeyboardView_legend);
+        t.recycle();
+    }
+
+    @SuppressLint("HandlerLeak")
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mHandler == null) {
+            mHandler = new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case MSG_SHOW_PREVIEW:
+                            break;
+                        case MSG_REPEAT:
+                            break;
+                        case MSG_REMOVE_PREVIEW:
+                            break;
+                        case MSG_LONGPRESS:
+                            break;
+                    }
+                }
+            };
+        }
+    }
+
+    public void setKeyboard(Keyboard keyboard) {
+        mKeyboard = keyboard;
+        List<Keyboard.Key> keys = mKeyboard.getKeys();
+        mKeys = keys.toArray(new Keyboard.Key[0]);
+    }
+
+    @Override
+    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Round up a little
+        if (mKeyboard == null) {
+            setMeasuredDimension(mPaddingH * 2, mPaddingV * 2);
+        } else {
+            int width = mKeyboard.getMinWidth() + mPaddingH * 2;
+            if (MeasureSpec.getSize(widthMeasureSpec) < width + 10) {
+                width = MeasureSpec.getSize(widthMeasureSpec);
+            }
+            setMeasuredDimension(width, mKeyboard.getHeight() + mPaddingV * 2 + mLegendHeight);
+        }
+    }
+
+    @SuppressLint("DrawAllocation")
+    @Override
+    public void onDraw(Canvas canvas) {
+        canvas.setDrawFilter(filter);
+        mPaint.setColor(mLegendBackground);
+        canvas.drawRect(0, 0, getWidth(), mLegendHeight, mPaint);
+        mPaint.setTypeface(source_han_sans_sc_medium);
+        mPaint.setTextSize(sp2px(20));
+        mPaint.setColor(mBtnCancelColor);
+        drawCenterText(canvas, mPaint, "取消", 0, 0, mLegendBtnWidth, mLegendHeight);
+        mPaint.setColor(mBtnConfirmColor);
+        drawCenterText(canvas, mPaint, "确定", getWidth() - mLegendBtnWidth, 0, getWidth(), mLegendHeight);
+        if (!TextUtils.isEmpty(mLegend)) {
+            mPaint.setTypeface(source_han_sans_sc_normal);
+            mPaint.setColor(Color.WHITE);
+            mPaint.setLetterSpacing(.2f);
+            drawCenterText(canvas, mPaint, mLegend, 0, 0, getWidth(), mLegendHeight);
+        }
+
+        mPaint.setTextSize(sp2px(25));
+        mPaint.setTypeface(roboto_normal);
+        for (Keyboard.Key key : mKeyboard.getKeys()) {
+            float left = mPaddingH + key.x;
+            float top = mLegendHeight + mPaddingV + key.y;
+            float right = mPaddingH + key.x + key.width;
+            float bottom = mLegendHeight + mPaddingV + key.y + key.height;
+
+
+            if (key.label.equals("del")) {
+                mPaint.setColor(mKeyBackgroundColor);
+                mBitmapPaint.setColorFilter(colorFilterWhite);
+                canvas.drawRoundRect(left, top, right, bottom, radius, radius, mPaint);
+                Bitmap bmCap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_del);
+                Rect src = new Rect(0, 0, bmCap.getWidth(), bmCap.getHeight());
+                float bmLeft = left + (key.width - bmCap.getWidth()) / 2f;
+                float bmTop = top + (key.height - bmCap.getHeight()) / 2f;
+                RectF dst = new RectF(bmLeft, bmTop, bmLeft + bmCap.getWidth(), bmTop + bmCap.getHeight());
+                canvas.drawBitmap(bmCap, src, dst, mBitmapPaint);
+            } else if (key.label.equals("shift")) {
+                if (cap) {
+                    mPaint.setColor(Color.WHITE);
+                    mBitmapPaint.setColorFilter(colorFilterBlack);
+                } else {
+                    mPaint.setColor(mKeyBackgroundColor);
+                    mBitmapPaint.setColorFilter(colorFilterWhite);
+                }
+                canvas.drawRoundRect(left, top, right, bottom, radius, radius, mPaint);
+                Bitmap bmCap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_cap);
+                Rect src = new Rect(0, 0, bmCap.getWidth(), bmCap.getHeight());
+                float bmLeft = left + (key.width - bmCap.getWidth()) / 2f;
+                float bmTop = top + (key.height - bmCap.getHeight()) / 2f;
+                RectF dst = new RectF(bmLeft, bmTop, bmLeft + bmCap.getWidth(), bmTop + bmCap.getHeight());
+                canvas.drawBitmap(bmCap, src, dst, mBitmapPaint);
+            } else {
+                mPaint.setColor(mKeyBackgroundColor);
+                canvas.drawRoundRect(left, top, right, bottom, radius, radius, mPaint);
+                mPaint.setColor(Color.WHITE);
+                drawCenterText(canvas, mPaint, cap ? key.label.toString().toUpperCase() : key.label.toString(), left, top, right, bottom);
+            }
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent e) {
+        final long eventTime = e.getEventTime();
+
+        switch (e.getAction()) {
+            case MotionEvent.ACTION_UP:
+                if (e.getY() > mLegendHeight) {
+                    int touchX = (int) (e.getX() - mPaddingH);
+                    int touchY = (int) (e.getY() - mLegendHeight - mPaddingV);
+                    int keyIndex = getKeyIndices(touchX, touchY, null);
+                    mCurrentKey = keyIndex;
+                    detectAndSendKey(mCurrentKey, touchX, touchY, eventTime);
+                } else {
+                    if (e.getX() < mLegendBtnWidth) {
+                        hide();
+                        if (mKeyboardActionListener != null) {
+                            mKeyboardActionListener.onKey(KEYCODE_CANCEL, new int[0]);
+                        }
+                    } else if (e.getX() > getWidth() - mLegendBtnWidth) {
+                        if (mKeyboardActionListener != null) {
+                            mKeyboardActionListener.onKey(KEYCODE_DONE, new int[0]);
+                        }
+                    }
+                }
+                break;
+        }
+
+        return true;
+    }
+
+
+    private int getKeyIndices(int x, int y, int[] allKeys) {
+        final Keyboard.Key[] keys = mKeys;
+        int primaryIndex = NOT_A_KEY;
+        int closestKey = NOT_A_KEY;
+        int closestKeyDist = mProximityThreshold + 1;
+        java.util.Arrays.fill(mDistances, Integer.MAX_VALUE);
+        int[] nearestKeyIndices = mKeyboard.getNearestKeys(x, y);
+        final int keyCount = nearestKeyIndices.length;
+        for (int i = 0; i < keyCount; i++) {
+            final Keyboard.Key key = keys[nearestKeyIndices[i]];
+            int dist = 0;
+            boolean isInside = key.isInside(x, y);
+            if (isInside) {
+                primaryIndex = nearestKeyIndices[i];
+            }
+
+            if (((mProximityCorrectOn
+                    && (dist = key.squaredDistanceFrom(x, y)) < mProximityThreshold)
+                    || isInside)
+                    && key.codes[0] > 32) {
+                // Find insertion point
+                final int nCodes = key.codes.length;
+                if (dist < closestKeyDist) {
+                    closestKeyDist = dist;
+                    closestKey = nearestKeyIndices[i];
+                }
+
+                if (allKeys == null) continue;
+
+                for (int j = 0; j < mDistances.length; j++) {
+                    if (mDistances[j] > dist) {
+                        // Make space for nCodes codes
+                        System.arraycopy(mDistances, j, mDistances, j + nCodes,
+                                mDistances.length - j - nCodes);
+                        System.arraycopy(allKeys, j, allKeys, j + nCodes,
+                                allKeys.length - j - nCodes);
+                        for (int c = 0; c < nCodes; c++) {
+                            allKeys[j + c] = key.codes[c];
+                            mDistances[j + c] = dist;
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+        if (primaryIndex == NOT_A_KEY) {
+            primaryIndex = closestKey;
+        }
+        return primaryIndex;
+    }
+
+    private void detectAndSendKey(int index, int x, int y, long eventTime) {
+        if (index != NOT_A_KEY && index < mKeys.length) {
+            final Keyboard.Key key = mKeys[index];
+            if (key.text != null) {
+                mKeyboardActionListener.onText(key.text);
+                mKeyboardActionListener.onRelease(NOT_A_KEY);
+            } else {
+                int code = key.codes[0];
+                //TextEntryState.keyPressedAt(key, x, y);
+                int[] codes = new int[MAX_NEARBY_KEYS];
+                Arrays.fill(codes, NOT_A_KEY);
+                getKeyIndices(x, y, codes);
+                mKeyboardActionListener.onKey(code, codes);
+                mKeyboardActionListener.onRelease(code);
+
+                if (mKeys[index].label.equals("shift")) {
+                    setCap(!cap);
+                    postInvalidate();
+                }
+            }
+            mLastSentIndex = index;
+            mLastTapTime = eventTime;
+        }
+    }
+
+    public int sp2px(float sp) {
+        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
+                getContext().getResources().getDisplayMetrics());
+    }
+
+    public int dp2px(float dp) {
+        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
+                getContext().getResources().getDisplayMetrics());
+    }
+
+    private void drawCenterText(Canvas canvas, Paint paint, String text, float left, float top, float right, float bottom) {
+        float textWidth = paint.measureText(text);
+        float baseLineY = Math.abs(paint.ascent() + paint.descent()) / 2 + (top + bottom) / 2;
+        canvas.drawText(text, (left + right) / 2 - textWidth / 2, baseLineY, paint);
+    }
+}

+ 5 - 0
app/src/main/res/drawable/bg_edit.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@android:color/white" />
+    <corners android:radius="4dp" />
+</shape>

+ 5 - 0
app/src/main/res/drawable/bg_key.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#444857" />
+    <corners android:radius="2dp" />
+</shape>

+ 8 - 0
app/src/main/res/drawable/cursor.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <size android:width="1dp" android:height="10dp" />
+    <solid android:color="@android:color/black" />
+    <padding
+        android:bottom="-11sp"
+        android:top="2sp" />
+</shape>

BIN
app/src/main/res/font/source_han_sans_sc_medium.otf


+ 73 - 0
app/src/main/res/layout/activity_login.xml

@@ -0,0 +1,73 @@
+<?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:id="@+id/parent_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:keepScreenOn="true"
+    tools:context=".LoginActivity">
+
+    <ImageView
+        android:id="@+id/iv_logo"
+        android:layout_width="162dp"
+        android:layout_height="41dp"
+        android:layout_marginTop="86dp"
+        android:src="@mipmap/logo"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="61dp"
+        android:fontFamily="@font/fzqkbysjw"
+        android:text="分支机构\n共享财富空间系统"
+        android:textAlignment="center"
+        android:textColor="@color/colorPrimary"
+        android:textSize="43sp"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/iv_logo" />
+
+    <com.ht.gate.UnlockView
+        android:id="@+id/unlock_view"
+        android:layout_width="338dp"
+        android:layout_height="71dp"
+        android:layout_marginTop="158dp"
+        app:hint="滑动登录"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv1" />
+
+    <EditText
+        android:id="@+id/et"
+        android:layout_width="match_parent"
+        android:layout_height="85dp"
+        android:layout_marginLeft="28dp"
+        android:layout_marginTop="360dp"
+        android:layout_marginRight="28dp"
+        android:background="@drawable/bg_edit"
+        android:gravity="center"
+        android:maxLines="1"
+        android:textSize="37sp"
+        android:visibility="gone"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.ht.gate.view.CustomKeyboardView
+        android:id="@+id/keyboard_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="#333641"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:legend="请输入共享空间ID" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 27 - 36
app/src/main/res/layout/activity_main.xml

@@ -4,8 +4,18 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:keepScreenOn="true"
-    tools:context=".MainActivity">
+    tools:context=".activity.MainActivity">
+
+    <ImageButton
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="18dp"
+        android:layout_marginRight="18dp"
+        android:background="@android:color/transparent"
+        android:padding="0dp"
+        android:src="@mipmap/icon_setting"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
 
     <ImageView
         android:id="@+id/iv_logo"
@@ -23,7 +33,7 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="61dp"
         android:fontFamily="@font/fzqkbysjw"
-        android:text="分支机构\n共享财富空间系统"
+        android:text="财富管理室"
         android:textAlignment="center"
         android:textColor="@color/colorPrimary"
         android:textSize="43sp"
@@ -31,44 +41,25 @@
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintTop_toBottomOf="@id/iv_logo" />
 
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/unlock"
-        android:layout_width="338dp"
-        android:layout_height="70dp"
-        android:layout_marginTop="158dp"
-        android:background="@drawable/bg_unlock"
+    <TextView
+        android:id="@+id/tv2"
+        android:layout_width="wrap_content"
+        android:layout_height="227dp"
+        android:fontFamily="@font/fzqkbysjw"
+        android:gravity="center"
+        android:text="A01"
+        android:textAlignment="center"
+        android:textColor="@color/colorPrimary"
+        android:textSize="208sp"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/tv1">
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:fontFamily="@font/source_han_sans_sc_light"
-            android:text="滑动解锁"
-            android:textColor="@android:color/white"
-            android:textSize="25sp"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintLeft_toLeftOf="parent"
-            app:layout_constraintRight_toRightOf="parent"
-            app:layout_constraintTop_toTopOf="parent" />
-
-        <ImageView
-            android:id="@+id/iv_unlock"
-            android:layout_width="56dp"
-            android:layout_height="56dp"
-            android:layout_marginLeft="7dp"
-            android:src="@mipmap/icon_unlock"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintLeft_toLeftOf="parent"
-            app:layout_constraintTop_toTopOf="parent" />
-    </androidx.constraintlayout.widget.ConstraintLayout>
+        app:layout_constraintTop_toBottomOf="@id/tv1" />
 
     <com.ht.gate.UnlockView
         android:layout_width="338dp"
-        android:layout_height="70dp"
-        android:layout_marginTop="158dp"
+        android:layout_height="71dp"
+        android:layout_marginTop="41dp"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/unlock" />
+        app:layout_constraintTop_toBottomOf="@id/tv2" />
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 7 - 0
app/src/main/res/layout/alphabetic_keyboard.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+</LinearLayout>

BIN
app/src/main/res/mipmap-xhdpi/icon_cap.png


BIN
app/src/main/res/mipmap-xhdpi/icon_del.png


BIN
app/src/main/res/mipmap-xxhdpi/icon_cap.png


BIN
app/src/main/res/mipmap-xxhdpi/icon_del.png


BIN
app/src/main/res/mipmap-xxhdpi/icon_setting.png


BIN
app/src/main/res/mipmap-xxxhdpi/icon_cap.png


BIN
app/src/main/res/mipmap-xxxhdpi/icon_del.png


BIN
app/src/main/res/mipmap-xxxhdpi/icon_setting.png


+ 10 - 0
app/src/main/res/values/attr.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="CustomKeyboardView">
+        <attr name="legend" format="string" />
+    </declare-styleable>
+
+    <declare-styleable name="UnlockView">
+        <attr name="hint" format="string" />
+    </declare-styleable>
+</resources>

+ 1 - 1
app/src/main/res/values/colors.xml

@@ -2,6 +2,6 @@
 <resources>
     <color name="colorPrimary">#E4BF85</color>
     <color name="colorPrimaryDark">#00574B</color>
-    <color name="colorAccent">#D81B60</color>
+    <color name="colorAccent">#222639</color>
     <color name="windowBackground">#222639</color>
 </resources>

+ 1 - 1
app/src/main/res/values/styles.xml

@@ -8,7 +8,7 @@
         <item name="colorAccent">@color/colorAccent</item>
         <item name="android:windowBackground">@color/windowBackground</item>
         <item name="android:windowFullscreen">true</item>
-        <item name="android:fontFamily">@font/source_han_sans_sc_normal</item>
+<!--        <item name="android:fontFamily">@font/source_han_sans_sc_normal</item>-->
     </style>
 
 </resources>

+ 177 - 0
app/src/main/res/xml/custom_keyboard.xml

@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:verticalGap="1.3125%p"
+    android:keyWidth="8.25%p"
+    android:keyHeight="6.916%p"
+    android:horizontalGap="1.590909%p">
+    <Row>
+        <Key
+            android:codes="49"
+            android:keyWidth="8.25%p"
+            android:keyLabel="1" />
+        <Key
+            android:codes="50"
+            android:keyWidth="8.25%p"
+            android:keyLabel="2" />
+        <Key
+            android:codes="51"
+            android:keyWidth="8.25%p"
+            android:keyLabel="3" />
+        <Key
+            android:codes="52"
+            android:keyWidth="8.25%p"
+            android:keyLabel="4" />
+        <Key
+            android:codes="53"
+            android:keyWidth="8.25%p"
+            android:keyLabel="5" />
+        <Key
+            android:codes="54"
+            android:keyWidth="8.25%p"
+            android:keyLabel="6" />
+        <Key
+            android:codes="55"
+            android:keyWidth="8.25%p"
+            android:keyLabel="7" />
+        <Key
+            android:codes="56"
+            android:keyWidth="8.25%p"
+            android:keyLabel="8" />
+        <Key
+            android:codes="57"
+            android:keyWidth="8.25%p"
+            android:keyLabel="9" />
+        <Key
+            android:codes="48"
+            android:keyWidth="8.25%p"
+            android:keyLabel="0" />
+    </Row>
+
+    <Row>
+        <Key
+            android:codes="81"
+            android:keyWidth="8.25%p"
+            android:keyLabel="q" />
+        <Key
+            android:codes="87"
+            android:keyWidth="8.25%p"
+            android:keyLabel="w" />
+        <Key
+            android:codes="69"
+            android:keyWidth="8.25%p"
+            android:keyLabel="e" />
+        <Key
+            android:codes="82"
+            android:keyWidth="8.25%p"
+            android:keyLabel="r" />
+        <Key
+            android:codes="84"
+            android:keyWidth="8.25%p"
+            android:keyLabel="t" />
+        <Key
+            android:codes="89"
+            android:keyWidth="8.25%p"
+            android:keyLabel="y" />
+        <Key
+            android:codes="85"
+            android:keyWidth="8.25%p"
+            android:keyLabel="u" />
+        <Key
+            android:codes="73"
+            android:keyWidth="8.25%p"
+            android:keyLabel="i" />
+        <Key
+            android:codes="79"
+            android:keyWidth="8.25%p"
+            android:keyLabel="o" />
+        <Key
+            android:codes="80"
+            android:keyWidth="8.25%p"
+            android:keyLabel="p" />
+    </Row>
+
+    <Row>
+        <Key
+            android:codes="65"
+            android:keyWidth="8.25%p"
+            android:keyLabel="-" />
+        <Key
+            android:codes="65"
+            android:keyWidth="8.25%p"
+            android:keyLabel="a" />
+        <Key
+            android:codes="83"
+            android:keyWidth="8.25%p"
+            android:keyLabel="s" />
+        <Key
+            android:codes="68"
+            android:keyWidth="8.25%p"
+            android:keyLabel="d" />
+        <Key
+            android:codes="70"
+            android:keyWidth="8.25%p"
+            android:keyLabel="f" />
+        <Key
+            android:codes="71"
+            android:keyWidth="8.25%p"
+            android:keyLabel="g" />
+        <Key
+            android:codes="72"
+            android:keyWidth="8.25%p"
+            android:keyLabel="h" />
+        <Key
+            android:codes="74"
+            android:keyWidth="8.25%p"
+            android:keyLabel="j" />
+        <Key
+            android:codes="75"
+            android:keyWidth="8.25%p"
+            android:keyLabel="k" />
+        <Key
+            android:codes="76"
+            android:keyWidth="8.25%p"
+            android:keyLabel="l" />
+    </Row>
+
+    <Row>
+        <Key
+            android:codes="16"
+            android:keyWidth="13.125%p"
+            android:keyLabel="shift" />
+        <Key
+            android:codes="90"
+            android:keyWidth="8.25%p"
+            android:keyLabel="z" />
+        <Key
+            android:codes="88"
+            android:keyWidth="8.25%p"
+            android:keyLabel="x" />
+        <Key
+            android:codes="67"
+            android:keyWidth="8.25%p"
+            android:keyLabel="c" />
+        <Key
+            android:codes="86"
+            android:keyWidth="8.25%p"
+            android:keyLabel="v" />
+        <Key
+            android:codes="66"
+            android:keyWidth="8.25%p"
+            android:keyLabel="b" />
+        <Key
+            android:codes="78"
+            android:keyWidth="8.25%p"
+            android:keyLabel="n" />
+        <Key
+            android:codes="77"
+            android:keyWidth="8.25%p"
+            android:keyLabel="m" />
+        <Key
+            android:codes="-5"
+            android:isRepeatable="true"
+            android:keyWidth="13.125%p"
+            android:keyLabel="del" />
+        <!--android:keyIcon="@drawable/keyboard_confirm_bg"-->
+    </Row>
+
+</Keyboard>