天天看點

SurfaceView作為底層,控件平移後,被遮擋的解決辦法

最近在做視訊錄像的一個小功能,功能不多,就錄像,儲存,取消。界面類似微信那樣。

SurfaceView作為底層,控件平移後,被遮擋的解決辦法

界面是這樣的,額,因為UI沒給我圖,右上角是切換攝像頭,指紋那裡是長按錄像。松開錄制結束,會出現兩個按鈕,位置和錄像按鈕一樣,然後動畫平移至兩邊,再把錄像隐藏

SurfaceView作為底層,控件平移後,被遮擋的解決辦法
SurfaceView作為底層,控件平移後,被遮擋的解決辦法

在界面上就類似這種效果,動畫也比較簡單。上界面代碼,代碼都比較簡單,可以跳過

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
    tools:context="com.envcloud.zhuhui.avoid.flood.ui.activity.RecordVideoActivity">

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@+id/iv_camera_change"
        android:layout_width="27dp"
        android:layout_height="27dp"
        android:padding="1dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="32dp"
        android:scaleType="fitCenter"
        android:src="@drawable/ic_refresh"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/iv_back"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@drawable/circle_green"
        android:layout_marginBottom="24dp"
        android:gravity="center"
        android:textSize="16sp"
        android:visibility="gone"
        android:textColor="@color/white"
        android:text="傳回"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/iv_save"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginBottom="24dp"
        android:visibility="gone"
        android:gravity="center"
        android:textSize="16sp"
        android:textColor="@color/white"
        android:text="儲存"
        android:background="@drawable/circle_purple"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ImageView
        android:id="@+id/iv_record"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:src="@drawable/ic_fingerprint"
        android:layout_marginBottom="24dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ImageView
        android:id="@+id/iv_finish"
        android:layout_width="25dp"
        android:layout_height="16dp"
        android:src="@drawable/ic_arrow_down"
        app:layout_constraintTop_toTopOf="@+id/iv_record"
        app:layout_constraintBottom_toBottomOf="@+id/iv_record"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/iv_record"/>

</android.support.constraint.ConstraintLayout>
           

後面應該是圖檔替換文字,是以取名先是iv_xxx了,不影響,iv_finish是一個結束目前activity,iv_back是不儲存視訊,重新拍攝,其他控件意思應該沒什麼問題。動畫部分的代碼:

private void initAnimator() {
        showSave = new AnimatorSet();
        ObjectAnimator backA = ObjectAnimator.ofFloat(ivBack, "translationX",
                0, -150);
        ObjectAnimator saveA = ObjectAnimator.ofFloat(ivSave, "translationX",
                0, 150);
        showSave.play(backA).with(saveA);
        showSave.setDuration(600);
        showSave.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                playing = false;
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                playing = true;//動畫未完成不允許點選事件
            }
        });

        showRecord = new AnimatorSet();
        ObjectAnimator backB = ObjectAnimator.ofFloat(ivBack, "translationX",
                -150, 0);
        ObjectAnimator saveB = ObjectAnimator.ofFloat(ivSave, "translationX",
                150, 0);
        showRecord.play(backB).with(saveB);
        showRecord.setDuration(600);
        showRecord.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                playing = false;
                visible(true);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                playing = true;//動畫未完成不允許點選事件
            }
        });
    }
           

然後visible(boolean bool)是在動畫開始前和結束後,控件的顯示,比方儲存和傳回在要錄像和錄像中開始是GONE,錄像結束錄像按鈕和轉換攝像頭是GONE,一個動畫是在錄制完成的時候showSave.start();一個是在點了傳回後showRecord.start();

結果最後的顯示效果是,用uc轉gif是真的模糊,将就着看吧:

SurfaceView作為底層,控件平移後,被遮擋的解決辦法

我懵逼了,這咋回事啊,為什麼會顯示一部份,像被遮擋了一樣,檢查了下代碼,沒東西遮住他,代碼位置也是在SurfaceView下面,而且顯示的這一部分剛好和錄像按鈕區域一緻。原理沒深究,我猜是(我猜的,看看就好,不要把這個作為了解,或者作為依據,這個還是需要看源碼的)SurfaceView在實時繪制的時候,除了一開始在螢幕上顯示,初始化的控件,會為他們留一片區域,位于SurfaceView的上方,其他區域都是在界面最上層。而那兩個按鈕,開始是設定成GONE的,界面初始化的時候在螢幕中沒有被繪制,是以沒有區域為他們預留。解決方法:将一個充滿螢幕寬度的,高和按鈕一樣的,背景是透明的View,放置在按鈕那個位置,讓SurfaceView在實時繪制的時候,總是留一片區域在下層。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
    tools:context="com.envcloud.zhuhui.avoid.flood.ui.activity.RecordVideoActivity">

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@+id/iv_camera_change"
        android:layout_width="27dp"
        android:layout_height="27dp"
        android:padding="1dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="32dp"
        android:scaleType="fitCenter"
        android:src="@drawable/ic_refresh"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:layout_width="match_parent"
        android:layout_height="70dp"
        app:layout_constraintTop_toTopOf="@+id/iv_record"
        app:layout_constraintBottom_toBottomOf="@+id/iv_record"/>

    <TextView
        android:id="@+id/iv_back"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@drawable/circle_green"
        android:layout_marginBottom="24dp"
        android:gravity="center"
        android:textSize="16sp"
        android:visibility="gone"
        android:textColor="@color/white"
        android:text="傳回"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/iv_save"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginBottom="24dp"
        android:visibility="gone"
        android:gravity="center"
        android:textSize="16sp"
        android:textColor="@color/white"
        android:text="儲存"
        android:background="@drawable/circle_purple"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ImageView
        android:id="@+id/iv_record"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:src="@drawable/ic_fingerprint"
        android:layout_marginBottom="24dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ImageView
        android:id="@+id/iv_finish"
        android:layout_width="25dp"
        android:layout_height="16dp"
        android:src="@drawable/ic_arrow_down"
        app:layout_constraintTop_toTopOf="@+id/iv_record"
        app:layout_constraintBottom_toBottomOf="@+id/iv_record"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/iv_record"/>

</android.support.constraint.ConstraintLayout>
           

java代碼不需要改任何東西,上效果圖:

SurfaceView作為底層,控件平移後,被遮擋的解決辦法

醬醬,居然成功了。點選也是完美,沒有沖突什麼的!