Android入门:简单视频进度条

        继续学习Android,使用监听和消息处理来实现一个简单的视频进度条。

一、效果预览

二、布局

        使用VideoView播放视频,在VideoView底部添加播放进度条,进度条左右分别显示当前播放时间和视频总时间。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <VideoView
        android:id="@+id/video"
        android:layout_width="match_parent"
        android:layout_height="100pt"
        android:keepScreenOn="true" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_alignBottom="@+id/video">

        <TextView
            android:id="@+id/leftTime"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:textColor="#B1AFAF"
            android:layout_weight="2"/>

        <SeekBar
            android:id="@+id/seekbar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="8"/>

        <TextView
            android:id="@+id/rightTime"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:textColor="#B1AFAF"
            android:layout_weight="2"/>
    </LinearLayout>
    
</RelativeLayout>

三、实现

        VideoView可以通过getDuration方法获取视频总长度,调用seekbar.setMax将视频长度与进度条长度同步;设置了总长度后,我们还需要在改变当前进度条进度时,同时改变视频的播放进度,SeekBar可以设置一个监听器,我们需要在进度改变时执行相应的操作。

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                handler.removeMessages(1);
                if(b) {
                    videoView.seekTo(i);
                }
                Message message = Message.obtain();
                message.arg1 = videoView.getDuration();
                message.arg2 = videoView.getCurrentPosition();
                message.what=1;
                //handler.sendMessageDelayed(message,100);
                handler.sendMessage(message);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        这里使用发送消息来同步时间,各个组件的监听中只需要负责发送需要改变的时间和总时间,消息处理中会执行我们定义的方法来更改对应的UI。

四、全部代码

        makeTimeString():实现了对总时间的格式转换,用于显示当前播放时间和总时间。

public class VideoActivity extends AppCompatActivity {

    private VideoView videoView;
    private SeekBar seekBar;
    private TextView leftTime;
    private TextView rightTime;

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            switch (msg.what){
                case 1:
                    int allLength = msg.arg1;
                    int currentPosition = msg.arg2;

                    leftTime.setText(makeTimeString(currentPosition));
                    rightTime.setText(makeTimeString(allLength));
                    seekBar.setProgress(currentPosition);

                    msg = Message.obtain();
                    msg.arg1 = videoView.getDuration();
                    msg.arg2 = videoView.getCurrentPosition();
                    msg.what = 1;
                    if(videoView.isPlaying()){
                        handler.sendMessageDelayed(msg,100);
                    }
                    break;
            }
        }
    };

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

        seekBar=findViewById(R.id.seekbar);
        leftTime=findViewById(R.id.leftTime);
        rightTime=findViewById(R.id.rightTime);
        videoView=findViewById(R.id.video);

        //String videoPath = "https:vfx.mtime.cn/Video/2019/07/12/mp4/190712140656051701.mp4";
        //videoView.setVideoPath(videoPath);
        Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.video);

        videoView.setVideoURI(uri);
        videoView.start();
        videoView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(videoView.isPlaying())
                    videoView.pause();
                else {
                    handler.removeMessages(1);
                    videoView.start();

                    Message message = Message.obtain();
                    message.arg1 = videoView.getDuration();
                    message.arg2 = videoView.getCurrentPosition();
                    message.what=1;
                    handler.sendMessageDelayed(message,100);
                }
            }
        });

        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                seekBar.setMax(videoView.getDuration());

                Message message = Message.obtain();
                message.arg1 = videoView.getDuration();
                message.arg2 = videoView.getCurrentPosition();
                message.what=1;
                handler.sendMessageDelayed(message,100);
            }
        });

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                handler.removeMessages(1);
                if(b) {
                    videoView.seekTo(i);
                }
                Message message = Message.obtain();
                message.arg1 = videoView.getDuration();
                message.arg2 = videoView.getCurrentPosition();
                message.what=1;
                //handler.sendMessageDelayed(message,100);
                handler.sendMessage(message);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    //时间转换成字符串,用于显示当前播放时间和总时间
    private String makeTimeString(int secs) {
        String durationFormat = "%1$02d:%2$02d:%3$02d";
        StringBuilder sFormatBuilder = new StringBuilder();
        Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());
        sFormatBuilder.setLength(0);
        secs = secs / 1000;
        Object[] timeArgs = new Object[3];
        timeArgs[0] = secs / 3600;
        timeArgs[1] = (secs % 3600) / 60;
        timeArgs[2] = (secs % 3600 % 60) % 60;
        return sFormatter.format(durationFormat,timeArgs).toString().trim();
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
<:Arc> 是 WPF 中自定义的一个元素,可以用于显示圆角进度条。你可以使用该元素的 Stroke 和 StrokeThickness 属性来设置进度条的边框颜色和宽度,使用 StartAngle 和 EndAngle 属性来设置进度条的起始角度和结束角度,使用 ArcThickness 属性来设置进度条的厚度,使用 ArcBackground 和 ArcForeground 属性来设置进度条的背景色和前景色。具体使用方法可以参考下面的代码示例: ```xml <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ed="clr-namespace:WpfApp1" Title="MainWindow" Height="450" Width="800"> <Window.Resources> <Style x:Key="ArcStyle" TargetType="{x:Type ed:Arc}"> <Setter Property="Stroke" Value="Gray"/> <Setter Property="StrokeThickness" Value="10"/> <Setter Property="ArcBackground" Value="LightGray"/> <Setter Property="ArcForeground" Value="Green"/> </Style> </Window.Resources> <Grid> <ed:Arc Style="{StaticResource ArcStyle}" StartAngle="0" EndAngle="360" ArcThickness="60" Value="50"/> </Grid> </Window> ``` 这段代码定义了一个使用自定义元素 <ed:Arc> 的窗口,在窗口中定义了一个名为 "ArcStyle" 的样式,用于设置进度条的外观属性。在 Grid 中使用 <ed:Arc> 元素,并将样式应用到该元素上,设置了 StartAngle 和 EndAngle 属性为 0 和 360,表示显示一个完整的圆形进度条,设置了 ArcThickness 属性为 60,表示进度条的厚度为 60,设置了 Value 属性为 50,表示当前进度为 50%。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值