最近在做一款视频剪辑的app时,功能中会有视频时长剪切,需要选取视频的一块时长然后进行剪切。于是自定义了一个时长剪切View,下面简单分享下心得:

1.明确需求

自定义View的大致效果

功能:
1)左右可以拖动伸缩
2)左边的拖动条不可超出右边的拖动条
3)未选中区域暗黑显示
4)左右拖动条上方动态显示相应的时间

自定义View的适用范围

当前自定义View,适用于任何目标View的时长剪切。

2.代码设计

模型构建

由上面的效果图,可以将自定义View划分成6个部分:左遮罩、右遮罩、上下边框线、中间选择区域、左拖动条、右拖动条。

设计历程:最开始研究时长剪切这个功能的时候,总将预览帧列表与剪切耦合到一起。参照https://www.jianshu.com/p/55dcb62ca0b3
这篇文章的思路才设计出这个View。

上代码

根据我的上篇博客https://www.jianshu.com/p/51fe99e9eb70的套路:
1)定义画笔

     private Paint markPaint = new Paint();          //遮罩绘制器
    private Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);         //边框绘制器
    private Paint handleThumbPaint;   //拖动条绘制器
  ...   //定义画笔的属性

2)定义一些参数变量
包括画笔的宽度、遮罩、边框、拖动条的宽度、整体实际绑定的值。
- 整体实际绑定的值
一般是100,但是用户也可以自行设定。
3)作画
在onDraw方法中,绘制左遮罩、右遮罩、上下边框线、中间选择区域、左拖动条、右拖动条。
注意这里的拖动条是绘制的图片,调用
```canvas.drawBitmap```方法。
4)动画
定义拖动目标的枚举类型:

    public enum TouchHandle {
        LEFT,             //左边拖动条
        RIGHT,            //右边拖动条
        CENTER,           //中间进度拖动条
        NONE              //无任何拖动目标
    }

在onTouchEvent方法的MotionEvent.ACTION_DOWN方法里,根据x、y判断触摸区域,定义找到拖动目标。
在onTouchEvent方法的MotionEvent.ACTION_MOVE里,根据触摸目标和位移,调用invalidate()方法,从而刷新onDraw方法,并且将参数回传。
5)添加监听

 /**
     * 拖动选择后的结果
     */
    public interface OnRankListener{
        void onRank(TouchHandle touchHandle,float startValue,float endValue,float selectValue,float startX,float endX,float rightX);
    }

监听拖动结果的实际值与坐标值,给出坐标值是为了在外部动态的改变时间View的位置(这里我就没有将时间画出来了,这样会增加这个View的复杂度。)

3.如何使用这个View

布局,保持和目标View同高。

 <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="1dp"
            >
            <com.camnter.easyrecyclerview.widget.EasyRecyclerView
                android:id="@+id/erv_images"
                android:layout_width="match_parent"
                android:layout_height="@dimen/rank_bar_height"
                />
            <com.cz.pro1mediaeditmagichand.view.cut.RankBar
                android:id="@+id/rank_bar"
                android:layout_width="match_parent"
                android:layout_height="@dimen/rank_bar_height"/>
        </FrameLayout>
 rankBar.setFillValue(mediaDetailBean.getDuration());
 rankBar.setMinSelectValue(MIN_CUT_DURATION);
 rankBar.setOnRankListener();

4.取预览帧

自定义View的功能完成了,但是时长剪切的整体功能并没有完成。
1)取预览帧
参照https://www.jianshu.com/p/55dcb62ca0b3可以将预览帧取出来
2)确定预览帧的个数
https://www.jianshu.com/p/55dcb62ca0b3的方法,我看得不是很明白,就自己写了一个算法:
这样就能保证视频的帧数均匀的分布在列表上

    /**
     * 根据分段函数,2元一次方程,来合理分配帧数。(用数学,用理性的思维来解决问题。)
     帧数(y)
     *
     30                ###########
     *               #
     *             #
     10 ##########
     *
     *
     * **********10****120***************************** 时长(x)
     * @return
     */
    private int getThumbsCount(){
        long duration = mediaDetailBean.getDuration();
        if(duration < 10*1000){
            return 10;
        }else if(duration >= 10*1000 && duration <= 120*1000){
            return (int) ((2.0/11) * duration/1000f + 90.0/11);
        }else{
            return 30;
        }
    }

# 源码:

如有疑惑或者好的建议,或者想纠正作者的博文,请联系如下
公众号:微信公众号搜索“修符道人”或者扫描下方二维码

微信号:XinYi1349308479
QQ邮箱:1349308479@qq.com


0 条评论

发表回复

您的电子邮箱地址不会被公开。