自定义控件系列四 (仿YouTube拖拽视频控件的实现)

您的浏览器不支持播放该视频!复制链接浏览器打开 http://zhx02.xiaoxingxing.online/2020/03/29/4ee85d854030a7b98001dc9e9f201b92.mp4

实现这个拖拽动画最重要的我们需要重写一下基本控件方法,setHeight,setWidht,setMarintop属性等,不然我们无法使用属性动画来实现,整个过程将会复杂许多。上节也提到了要想在属性动画中使用height widht这些属性我们就需要去实现相应的set方法。
先贴出完成代码,然后再讲解:
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<com.gesture.zhx.zhxgesture.CustomUI.MyFramLayout
    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/m4_group"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="bottom"
    android:orientation="vertical">

    <com.gesture.zhx.zhxgesture.CustomUI.MyVideoView
        android:id="@+id/video"
        android:layout_width="match_parent"
        android:layout_height="200dp">
    </com.gesture.zhx.zhxgesture.CustomUI.MyVideoView>

    <com.gesture.zhx.zhxgesture.CustomUI.MyScrollView
        android:id="@+id/scr"
        android:layout_marginTop="200dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:background="#ff0000"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#ffff00"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#4678ff"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#ff0000"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#ffff00"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#4678ff"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#ff0000"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#ffff00"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
            <TextView
                android:background="#4678ff"
                android:layout_width="match_parent"
                android:layout_height="100dp">
            </TextView>
        </LinearLayout>
    </com.gesture.zhx.zhxgesture.CustomUI.MyScrollView>
</com.gesture.zhx.zhxgesture.CustomUI.MyFramLayout>

mainactivity文件:

public class Main4Activity extends Activity {

    private int dx, dy, mx, my, ux, uy;
    private MyFramLayout m4Group;
    private MyVideoView video;
    private MyScrollView scr;
    private int residueHeight = 0, SumscrollY = 0, OffsetY = 0;
    private int groupHeight = 0, videoHeight = 0, scrHeight = 0;
    private int groupWidth = 0, videoWidth = 0, scrWidth = 0;
    private float alpha = 255;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        initView();
    }

    private void initView() {
        m4Group = (MyFramLayout) findViewById(R.id.m4_group);
        video = (MyVideoView) findViewById(R.id.video);
        scr = (MyScrollView) findViewById(R.id.scr);
        //网络数据
        String s = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
        Uri uri = Uri.parse(s);
        video.setVideoURI(uri);
        video.requestFocus();
        video.start();

        m4Group.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        dy = (int) event.getRawY();
                        SumscrollY = 0;
                        if (groupHeight == 0) groupHeight = m4Group.getHeight();
                        if (videoHeight == 0) videoHeight = video.getHeight();
                        if (scrHeight == 0) scrHeight = scr.getHeight();
                        if (residueHeight == 0) residueHeight = groupHeight - videoHeight;
                        if (groupWidth == 0) groupWidth = m4Group.getWidth();
                        if (videoWidth == 0) videoWidth = video.getWidth();
                        if (scrWidth == 0) scrWidth = scr.getWidth();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        my = (int) event.getRawY();
                        uploadView();
                        break;
                    case MotionEvent.ACTION_UP:
                        uy = (int) event.getRawY();
                        /**
                         * 抬起的时候判断最终落点在上半区域还是下半区域
                         * 如果是上半区域则向上恢复
                         * 如果是下半区域则向下执行运动
                         */
                        if (uy < groupHeight / 2) {
                            //上半区
                            resetTopVideoview();
                            resetTopScrollView();
                        } else {
                            //下半区
                            resetBottomVideoView();
                            resetBottomScrollView();
                        }
                        break;
                }
                return true;
            }
        });
    }

    private void uploadView() {
        OffsetY = my - dy;
        SumscrollY = video.getMargin()[1] + OffsetY;
        if (SumscrollY > residueHeight)
            SumscrollY = (int) residueHeight;
        if (SumscrollY < 0)
            SumscrollY = 0;

        alpha = txfloat((residueHeight - SumscrollY), residueHeight);
        int mr = (int) ((1f - alpha) * videoWidth / 2);
        scr.setAlpha(alpha);
        scr.setMarginTop(SumscrollY + video.getHeight());
        video.setMarginTop(SumscrollY);
        video.setMarginRight(mr);
        int h = (int) (videoHeight * alpha);
        if (h <= videoHeight / 3 *2){
            h = videoHeight /3 *2;
        }
        video.setHeight(h);
        dy = my;

    }

    private void resetTopVideoview() {
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator animator1 = ObjectAnimator.ofInt(video, "height", video.getHeight(), videoHeight);
        ObjectAnimator animator2 = ObjectAnimator.ofInt(video, "marginTop", video.getMargin()[1], 0);
        ObjectAnimator animator3 = ObjectAnimator.ofInt(video, "marginRight", video.getMargin()[2], 0);
        animatorSet.setDuration(600);
        animatorSet.playTogether(animator1, animator2, animator3);
        animatorSet.start();
    }

    private void resetTopScrollView() {
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(scr, "alpha", scr.getAlpha(), 255);
        ObjectAnimator animator2 = ObjectAnimator.ofInt(scr, "marginTop", scr.getMargin()[1], videoHeight);
        animatorSet.setDuration(600);
        animatorSet.playTogether(animator1, animator2);
        animatorSet.start();
    }

    private void resetBottomVideoView() {
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator animator1 = ObjectAnimator.ofInt(video, "height", video.getHeight(), videoHeight / 3 * 2);
        ObjectAnimator animator2 = ObjectAnimator.ofInt(video, "marginTop", video.getMargin()[1], residueHeight);
        ObjectAnimator animator3 = ObjectAnimator.ofInt(video, "marginRight", video.getMargin()[2], videoWidth / 2);
        animatorSet.setDuration(1200);
        animatorSet.playTogether(animator1, animator2, animator3);
        animatorSet.start();
    }

    private void resetBottomScrollView() {
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(scr, "alpha", scr.getAlpha(), 0);
        ObjectAnimator animator2 = ObjectAnimator.ofInt(scr, "marginTop", scr.getMargin()[1], residueHeight + video.getHeight());
        animatorSet.setDuration(600);
        animatorSet.playTogether(animator1, animator2);
        animatorSet.start();
    }

    public Float txfloat(int a, int b) {
        DecimalFormat df = new DecimalFormat("0.00");
        String s = String.valueOf(df.format((float) a / b));
        return Float.parseFloat(s);
    }

}

MyFramLayout文件:

public class MyFramLayout extends FrameLayout {

    public MyFramLayout(Context context){
        super(context);
    }

    public MyFramLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public void setHeight(int height) {
        ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams();
        params.height = height;
        setLayoutParams(params);
    }

    public void setWidth(int value) {
        LayoutParams params = (LayoutParams) getLayoutParams();
        params.width = value;
        setLayoutParams(params);
    }

    public void setMarginTop(int values){
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
        params.topMargin = values;
        setLayoutParams(params);
    }

    public void setMarginLeft(int values){
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
        params.leftMargin = values;
        setLayoutParams(params);
    }

    public void setMarginRight(int values){
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
        params.rightMargin = values;
        setLayoutParams(params);
    }

    public void setMarginBottom(int values){
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
        params.bottomMargin = values;
        setLayoutParams(params);
    }


    public int[] getMargin() {
        int[] arr = new int[6];
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
        arr[0] = params.leftMargin;
        arr[1] = params.topMargin;
        arr[2] = params.rightMargin;
        arr[3] = params.bottomMargin;
        arr[4] = params.height;
        arr[5] = params.width;
        return arr;
    }
}

MyScrollView,MyVideoView不多说与上面的MyFramLayout文件一样就写几个属性方法。
在我们手指按下的时候我们就记录控件初始化的高度,这些参数我们都需要用到后面,所以只需要赋值一次,在抬起来的时候我们分析手指是在屏幕上区域还是下区域,然后调用相应的方法实现动画。
在uploadView方法中我们需要去记录手指滑动的总距离,这里我们是获取videoview距离上面的高度加上此次的偏移量来算,为什么这样左,这样左有一个好处,就是当你再次按下的时候就能接着上次的距离来进行计算,不需要去判断是往上滚动还是往下滚动。
然后对videoview来说需要改变他的height margintop marginright三个属性
对Scrollview来说我们需要改变他的 alpha margintop 俩个属性
在相应方法中,计算出最后的结果值,传入当前的属性值即可。
整个逻辑还是有点绕的,不过自己动手试试也很好理解。
那么动画我们是实现了,activity的背景色我们怎么设置透明,

android:theme="@android:style/Theme.Translucent.NoTitleBar"

更改主题属性就可以了,那么在activity中我们怎么实现一个应用内所有界面悬浮播放的效果,这个可以用打开一个新窗口实现,类似于悬浮窗原理。
如果是一个fragment,那最好还是用悬浮窗原理去做,但是如果你的项目是一个activity加多一个fragment组成,那么你可以直接用fragment,把这个videofragment置于栈顶,并以后所有添加的fragment都置于第二层即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值