Browse Source

[feat]键盘插件,增加裁切布局,处理切换错乱问题

hezihao 8 months ago
parent
commit
c94eb15d59

+ 3 - 3
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/RouteComponent.kt

@@ -10,13 +10,13 @@ class RouteComponent @JvmOverloads constructor(
     context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
     context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
 ) : GroupComponent(context, attrs, defStyleAttr) {
 ) : GroupComponent(context, attrs, defStyleAttr) {
     /**
     /**
-     * 切换子组件,也就是先隐藏掉所有兄弟组件,再显示自己
+     * 路由切换子组件,也就是先隐藏掉所有兄弟组件,再显示自己
      *
      *
      * @param mutex 是否互斥,如果为true,则会隐藏其他子组件后,再显示自己,为false则是不隐藏兄弟组件,直接显示自己
      * @param mutex 是否互斥,如果为true,则会隐藏其他子组件后,再显示自己,为false则是不隐藏兄弟组件,直接显示自己
      */
      */
-    fun <T : IUIComponent> toggleChildComponent(
+    fun <T : IUIComponent> routeChildComponent(
         targetComponentClass: Class<T>,
         targetComponentClass: Class<T>,
-        mutex: Boolean = true
+        mutex: Boolean = false
     ) {
     ) {
         // 获取所有直接子组件
         // 获取所有直接子组件
         val directChildComponentList = getDirectChildComponentList()
         val directChildComponentList = getDirectChildComponentList()

+ 0 - 24
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/KeyBoardContainerComponent.kt

@@ -6,9 +6,6 @@ import android.view.View
 import com.atmob.keyboard_android.R
 import com.atmob.keyboard_android.R
 import com.atmob.keyboard_android.component.base.BaseUIComponent
 import com.atmob.keyboard_android.component.base.BaseUIComponent
 import com.atmob.keyboard_android.component.child.IKeyBoardContainerComponent
 import com.atmob.keyboard_android.component.child.IKeyBoardContainerComponent
-import com.atmob.keyboard_android.ext.setGone
-import com.atmob.keyboard_android.ext.setVisible
-import com.atmob.keyboard_android.util.KeyboardHolder
 
 
 /**
 /**
  * 键盘容器组件,包含多个键盘,例如拼音键盘和AI键盘,顶部是工具栏组件
  * 键盘容器组件,包含多个键盘,例如拼音键盘和AI键盘,顶部是工具栏组件
@@ -28,27 +25,6 @@ class KeyBoardContainerComponent @JvmOverloads constructor(
     }
     }
 
 
     override fun bindView(view: View) {
     override fun bindView(view: View) {
-        KeyboardHolder.getKeyboardService()?.run {
-            getKeyboardViewModel().let {
-                // 监听设置页是否打开,打开时,隐藏键盘内容
-                it.settingPageShowing.observe(getLifecycleOwner()) { isShowing ->
-                    if (isShowing) {
-                        vKeyboardContent.setGone()
-                    } else {
-                        // TODO: hezihao,这里显示键盘内容有问题,还需要判断其他页是否展示
-                        vKeyboardContent.setVisible()
-                    }
-                }
-                // 监听设置页是否打开,打开时,隐藏键盘内容
-                it.keyboardSelectPageShowing.observe(getLifecycleOwner()) { isShowing ->
-                    if (isShowing) {
-                        vKeyboardContent.setGone()
-                    } else {
-                        vKeyboardContent.setVisible()
-                    }
-                }
-            }
-        }
     }
     }
 
 
     override fun getComponentInterfaceClazz(): Class<IKeyBoardContainerComponent> {
     override fun getComponentInterfaceClazz(): Class<IKeyBoardContainerComponent> {

+ 3 - 3
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/root/KeyboardRootComponent.kt

@@ -34,14 +34,14 @@ class KeyboardRootComponent @JvmOverloads constructor(
     }
     }
 
 
     override fun switchVipPage() {
     override fun switchVipPage() {
-        vRouteComponent.toggleChildComponent(IVipPageComponent::class.java, false)
+        vRouteComponent.routeChildComponent(IVipPageComponent::class.java)
     }
     }
 
 
     override fun switchLoginPage() {
     override fun switchLoginPage() {
-        vRouteComponent.toggleChildComponent(ILoginPageComponent::class.java, false)
+        vRouteComponent.routeChildComponent(ILoginPageComponent::class.java)
     }
     }
 
 
     override fun switchSettingPage() {
     override fun switchSettingPage() {
-        vRouteComponent.toggleChildComponent(ISettingComponent::class.java, false)
+        vRouteComponent.routeChildComponent(ISettingComponent::class.java)
     }
     }
 }
 }

+ 120 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/widget/ClippedLayout.java

@@ -0,0 +1,120 @@
+package com.atmob.keyboard_android.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.atmob.keyboard_android.R;
+
+/**
+ * 裁切背景顶部的布局
+ */
+public class ClippedLayout extends FrameLayout {
+    private float topOffset;
+
+    private Paint debugPaint;
+
+    public ClippedLayout(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public ClippedLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public ClippedLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        setup(context, attrs, defStyleAttr);
+    }
+
+    public ClippedLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        setup(context, attrs, defStyleAttr);
+    }
+
+    private void setup(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        // 初始化自定义属性
+        initAttrs(context, attrs);
+        // 初始化debug模式下的画笔
+        initDebugPaint();
+        // 默认ViewGroup不调用onDraw()方法,设置为false,则调用
+        setWillNotDraw(false);
+        // 设置禁用硬件加速
+        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+    }
+
+    /**
+     * 初始化自定义属性
+     */
+    private void initAttrs(@NonNull Context context, @Nullable AttributeSet attrs) {
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ClippedLayout);
+        topOffset = typedArray.getDimension(
+                R.styleable.ClippedLayout_cl_clip_top_offset,
+                0
+        );
+        typedArray.recycle();
+    }
+
+    /**
+     * 初始化debug模式下的画笔
+     */
+    private void initDebugPaint() {
+        debugPaint = new Paint();
+        // 半透明红色
+        debugPaint.setColor(Color.parseColor("#66FF0000"));
+        debugPaint.setStyle(Paint.Style.FILL);
+        debugPaint.setAntiAlias(true);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // 裁切后,让顶部透明区域,不消费点击事件
+        if (event.getY() < topOffset) {
+            return false;
+        }
+        return super.onTouchEvent(event);
+    }
+
+    /**
+     * 注意,要重写draw方法,而不是onDraw,ViewGroup的背景是在draw方法中执行的,而View是在onDraw方法
+     */
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        // 预览模式:完整绘制背景,红色区域
+        if (isInEditMode()) {
+            super.draw(canvas);
+            canvas.drawRect(0, 0, getWidth(), topOffset, debugPaint);
+        } else {
+            // 正式环境:应用裁剪
+            canvas.save();
+            canvas.clipRect(0, topOffset, getWidth(), getHeight());
+            super.draw(canvas);
+            canvas.restore();
+        }
+    }
+
+    /**
+     * 动态设置顶部裁切大小
+     *
+     * @param dpValue 顶部裁切大小,单位为dp
+     */
+    public void setClipTopOffsetDp(float dpValue) {
+        topOffset = TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP,
+                dpValue,
+                getResources().getDisplayMetrics()
+        );
+        // 触发重绘
+        invalidate();
+    }
+}

+ 7 - 5
plugins/keyboard_android/android/src/main/res/layout/component_keyboard_select.xml

@@ -1,16 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.atmob.keyboard_android.widget.ClippedLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_width="match_parent"
     android:layout_height="@dimen/keyboard_height"
     android:layout_height="@dimen/keyboard_height"
-    tools:background="@mipmap/bg_keyboard">
+    android:background="@mipmap/bg_keyboard"
+    android:clickable="true"
+    app:cl_clip_top_offset="60dp">
 
 
     <androidx.constraintlayout.widget.ConstraintLayout
     <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_height="match_parent"
-        android:layout_marginTop="65dp"
-        android:clickable="true">
+        android:layout_marginTop="60dp">
 
 
         <androidx.recyclerview.widget.RecyclerView
         <androidx.recyclerview.widget.RecyclerView
             android:id="@+id/list"
             android:id="@+id/list"
@@ -26,6 +27,7 @@
             android:layout_width="32dp"
             android:layout_width="32dp"
             android:layout_height="32dp"
             android:layout_height="32dp"
             android:layout_marginStart="12dp"
             android:layout_marginStart="12dp"
+            android:layout_marginTop="5dp"
             android:src="@mipmap/ic_back_btn"
             android:src="@mipmap/ic_back_btn"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
             app:layout_constraintTop_toTopOf="parent" />
@@ -48,4 +50,4 @@
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent" />
             app:layout_constraintStart_toStartOf="parent" />
     </androidx.constraintlayout.widget.ConstraintLayout>
     </androidx.constraintlayout.widget.ConstraintLayout>
-</FrameLayout>
+</com.atmob.keyboard_android.widget.ClippedLayout>

+ 69 - 62
plugins/keyboard_android/android/src/main/res/layout/component_setting.xml

@@ -1,86 +1,93 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.atmob.keyboard_android.widget.ClippedLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_width="match_parent"
     android:layout_height="@dimen/keyboard_height"
     android:layout_height="@dimen/keyboard_height"
-    tools:background="@mipmap/bg_keyboard">
-
-    <ImageView
-        android:id="@+id/back_btn"
-        android:layout_width="32dp"
-        android:layout_height="32dp"
-        android:layout_marginStart="12dp"
-        android:layout_marginTop="65dp"
-        android:src="@mipmap/ic_back_btn"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <androidx.core.widget.NestedScrollView
+    android:background="@mipmap/bg_keyboard"
+    app:cl_clip_top_offset="60dp">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_height="wrap_content"
-        android:fillViewport="true"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/back_btn">
+        android:layout_marginTop="60dp">
+
+        <ImageView
+            android:id="@+id/back_btn"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_marginStart="12dp"
+            android:layout_marginTop="5dp"
+            android:src="@mipmap/ic_back_btn"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
 
 
-        <LinearLayout
+        <androidx.core.widget.NestedScrollView
             android:layout_width="match_parent"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
-            android:orientation="vertical">
+            android:fillViewport="true"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/back_btn">
 
 
-            <LinearLayout style="@style/setting_item_row">
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
 
 
-                <LinearLayout
-                    android:id="@+id/setting_custom_person_layout"
-                    style="@style/setting_item">
+                <LinearLayout style="@style/setting_item_row">
 
 
-                    <ImageView
-                        style="@style/setting_item_icon"
-                        android:src="@mipmap/ic_custom" />
+                    <LinearLayout
+                        android:id="@+id/setting_custom_person_layout"
+                        style="@style/setting_item">
 
 
-                    <TextView
-                        style="@style/setting_item_text"
-                        android:text="@string/setting_custom_person" />
-                </LinearLayout>
+                        <ImageView
+                            style="@style/setting_item_icon"
+                            android:src="@mipmap/ic_custom" />
 
 
-                <LinearLayout
-                    android:id="@+id/setting_market_layout"
-                    style="@style/setting_item2">
+                        <TextView
+                            style="@style/setting_item_text"
+                            android:text="@string/setting_custom_person" />
+                    </LinearLayout>
 
 
-                    <ImageView
-                        style="@style/setting_item_icon"
-                        android:src="@mipmap/ic_market" />
+                    <LinearLayout
+                        android:id="@+id/setting_market_layout"
+                        style="@style/setting_item2">
 
 
-                    <TextView
-                        style="@style/setting_item_text"
-                        android:text="@string/setting_market" />
-                </LinearLayout>
-            </LinearLayout>
+                        <ImageView
+                            style="@style/setting_item_icon"
+                            android:src="@mipmap/ic_market" />
 
 
-            <LinearLayout
-                style="@style/setting_item_row2"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/back_btn">
+                        <TextView
+                            style="@style/setting_item_text"
+                            android:text="@string/setting_market" />
+                    </LinearLayout>
+                </LinearLayout>
 
 
                 <LinearLayout
                 <LinearLayout
-                    android:id="@+id/setting_unlock_vip_layout"
-                    style="@style/setting_item">
+                    style="@style/setting_item_row2"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/back_btn">
 
 
-                    <ImageView
-                        style="@style/setting_item_icon"
-                        android:src="@mipmap/ic_vip" />
+                    <LinearLayout
+                        android:id="@+id/setting_unlock_vip_layout"
+                        style="@style/setting_item">
 
 
-                    <TextView
-                        style="@style/setting_item_text"
-                        android:text="@string/setting_unlock_vip" />
-                </LinearLayout>
+                        <ImageView
+                            style="@style/setting_item_icon"
+                            android:src="@mipmap/ic_vip" />
 
 
-                <LinearLayout
-                    style="@style/setting_item2"
-                    android:visibility="invisible" />
+                        <TextView
+                            style="@style/setting_item_text"
+                            android:text="@string/setting_unlock_vip" />
+                    </LinearLayout>
+
+                    <LinearLayout
+                        style="@style/setting_item2"
+                        android:visibility="invisible" />
+                </LinearLayout>
             </LinearLayout>
             </LinearLayout>
-        </LinearLayout>
-    </androidx.core.widget.NestedScrollView>
-</androidx.constraintlayout.widget.ConstraintLayout>
+        </androidx.core.widget.NestedScrollView>
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</com.atmob.keyboard_android.widget.ClippedLayout>

+ 8 - 0
plugins/keyboard_android/android/src/main/res/values/attrs_clipped_layout.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- 可裁切背景的View -->
+    <declare-styleable name="ClippedLayout">
+        <!-- 顶部的裁切区域的高度,单位为dp -->
+        <attr name="cl_clip_top_offset" format="dimension" />
+    </declare-styleable>
+</resources>