SurfaceView作为底层,控件平移后,被遮挡的解决办法

最近在做视频录像的一个小功能,功能不多,就录像,保存,取消。界面类似微信那样。

界面是这样的,额,因为UI没给我图,右上角是切换摄像头,指纹那里是长按录像。松开录制结束,会出现两个按钮,位置和录像按钮一样,然后动画平移至两边,再把录像隐藏

        

在界面上就类似这种效果,动画也比较简单。上界面代码,代码都比较简单,可以跳过

<?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的上方,其他区域都是在界面最上层。而那两个按钮,开始是设置成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代码不需要改任何东西,上效果图:

酱酱,居然成功了。点击也是完美,没有冲突什么的!

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要实现SurfaceView的缩放和平移,可以通过以下步骤进行操作: 1. 创建一个SurfaceView并设置好SurfaceHolder.Callback回调函数。 2. 在SurfaceHolder.Callback的surfaceCreated()方法中,获取SurfaceView的宽度和高度,并创建一个Bitmap对象来存储SurfaceView的内容。 3. 在SurfaceHolder.Callback的surfaceChanged()方法中,根据SurfaceView的宽度和高度,将Bitmap对象的大小设置为SurfaceView的大小。 4. 在SurfaceHolder.Callback的surfaceDestroyed()方法中,释放Bitmap对象的内存空间。 5. 在SurfaceView的onTouchEvent()方法中,实现手势缩放和平移,并调用draw()方法重新绘制SurfaceView。 6. 在SurfaceView的draw()方法中,将Bitmap对象绘制在SurfaceView上。 下面是一个简单的示例代码: ``` public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Bitmap mBitmap; private Canvas mCanvas; private float mScale = 1.0f; private float mTranslateX = 0.0f; private float mTranslateY = 0.0f; private float mLastX; private float mLastY; public MySurfaceView(Context context) { super(context); mHolder = getHolder(); mHolder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mBitmap.recycle(); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastX = event.getX(); mLastY = event.getY(); break; case MotionEvent.ACTION_MOVE: float deltaX = event.getX() - mLastX; float deltaY = event.getY() - mLastY; mTranslateX += deltaX; mTranslateY += deltaY; mLastX = event.getX(); mLastY = event.getY(); break; case MotionEvent.ACTION_POINTER_DOWN: if (event.getPointerCount() == 2) { float distance = distance(event); mScale = distance / distance(event.getX(0), event.getY(0), event.getX(1), event.getY(1)); } break; case MotionEvent.ACTION_POINTER_UP: if (event.getPointerCount() == 2) { mScale = 1.0f; } break; } draw(); return true; } private void draw() { Canvas canvas = mHolder.lockCanvas(); if (canvas != null) { canvas.drawColor(Color.WHITE); canvas.drawBitmap(mBitmap, mTranslateX, mTranslateY, null); mHolder.unlockCanvasAndPost(canvas); } } private float distance(MotionEvent event) { return distance(event.getX(0), event.getY(0), event.getX(1), event.getY(1)); } private float distance(float x1, float y1, float x2, float y2) { float deltaX = x2 - x1; float deltaY = y2 - y1; return (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY); } } ``` 在上面的代码中,我们实现了手势缩放和平移功能,并在draw()方法中将Bitmap对象绘制在SurfaceView上。在onTouchEvent()方法中,我们检测到手势事件后,更新缩放和平移的参数,并调用draw()方法重新绘制SurfaceView。注意,我们使用lockCanvas()方法获取Canvas对象来绘制SurfaceView的内容,使用unlockCanvasAndPost()方法将Canvas对象提交到SurfaceView上显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值