How to mark horizontal ProgressBar with different color at some index just like Youtube video yellow color ad marker in Android

Dny*_*h M 7 android

In my current app there is requirement to create custom video player and the special requirement is, to display or mark video progress-bar with different color at some given time-index just like Youtube marks its video with yellow color to indicate ads on its video progress bar.

For more clarity please check below screen-shot:

在此处输入图片说明

At this moment I'm done with Video Player functionality using VideoView and for now, I'm using Horizontal ProgressBar to show video progress. I did lot of research, but unfortunately no result so far. There is no compulsion to use only Horizontal ProgressBar, we can use SeekBar or inbuilt MediaController too, but the thing is we should be able to mark it with different color at some given position. Below is my code I have written so far:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000"
    android:paddingLeft="5dp"
    android:paddingTop="5dp"
    android:paddingRight="5dp"
    android:paddingBottom="5dp"
    tools:context=".MainActivity">

    <VideoView
        android:id="@+id/myVideo"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerInParent="true" />

    <RelativeLayout
        android:id="@+id/rlVidProgress"
        android:layout_width="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tvCurrentTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="20dp"
            android:text="00:00"
            android:textColor="@android:color/white"
            android:textSize="13dp"
            android:textStyle="bold" />

        <ProgressBar
            android:id="@+id/videoProgress"
            style="@android:style/Widget.ProgressBar.Horizontal"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@+id/tvTotalTime"
            android:layout_width="fill_parent"
            android:layout_toRightOf="@+id/tvCurrentTime"
            android:layout_height="10dp"
            android:layout_marginBottom="10dp" />

        <TextView
            android:id="@+id/tvTotalTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="5dp"
            android:text="00:00"
            android:textColor="@android:color/white"
            android:textSize="13dp"
            android:textStyle="bold" />

    </RelativeLayout>

    <TextView
        android:id="@+id/tvAutoSave"
        android:layout_width="wrap_content"
        android:textColor="@android:color/white"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="10dp"
        android:text="@string/click_to_auto_save_offer"
        android:background="@drawable/white_border_bg"
        android:textSize="13dp"
        android:layout_above="@+id/rlVidProgress"
        android:visibility="gone"
        android:paddingBottom="3dp"
        android:paddingTop="3dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textStyle="bold"
        android:layout_height="wrap_content" />

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
    ProgressBar videoProgress;
    TextView tvCurrentTime;
    Handler handler;
    VideoView vidView;
    String strTotalDuration;
    TextView tvAutoSave;
    Animation animFadeIn, animFadeOut;

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

        animFadeIn = new AlphaAnimation(0, 1);
        animFadeIn.setInterpolator(new DecelerateInterpolator()); //add this
        animFadeIn.setDuration(1000);

        animFadeOut = new AlphaAnimation(1, 0);
        animFadeOut.setInterpolator(new AccelerateInterpolator()); //and this
        //animFadeOut.setStartOffset(500);
        animFadeOut.setDuration(500);


        tvCurrentTime = (TextView) findViewById(R.id.tvCurrentTime);
        final TextView tvTotalTime = (TextView) findViewById(R.id.tvTotalTime);
        tvAutoSave = (TextView) findViewById(R.id.tvAutoSave);
        tvAutoSave.setOnClickListener(this);

        vidView = (VideoView)findViewById(R.id.myVideo);

        videoProgress = (ProgressBar) findViewById(R.id.videoProgress);
        videoProgress.setProgress(0);
        videoProgress.setMax(100);

        final String videoSource = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
        vidView.setKeepScreenOn(true);
        vidView.setVideoURI(Uri.parse(videoSource));
        vidView.setMediaController(null);

        handler = new Handler();
        // Define the code block to be executed
        final Runnable runnableCode = new Runnable() {
            @Override
            public void run()
            {
                updateCurrentTime();
                // Repeat this the same runnable code block again another 1 seconds
                // 'this' is referencing the Runnable object
                handler.postDelayed(this, 1000);
            }
        };

        vidView.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
        {
            @Override
            public void onCompletion(MediaPlayer mp)
            {
                if(tvAutoSave.getVisibility() == View.VISIBLE)
                {
                    tvAutoSave.setVisibility(View.GONE);
                    tvAutoSave.startAnimation(animFadeOut);
                }
            }
        });

        vidView.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
                                      {
                                          @Override
                                          public void onPrepared(MediaPlayer mp)
                                          {
                                              vidView.start();
                                              strTotalDuration = msToTimeConverter(vidView.getDuration());
                                              tvTotalTime.setText(""+strTotalDuration);
                                              // Start the initial runnable task by posting through the handler
                                              handler.post(runnableCode);
                                              //startHandler();
                                          }
                                      }


        );
    }


    private void updateCurrentTime()
    {
        if (videoProgress.getProgress() >= 100)
        {
            handler.removeMessages(0);
        }
        String currentPosition = msToTimeConverter(vidView.getCurrentPosition());

        String[] strArr = currentPosition.split(":");

        if(strArr.length==2 && (strArr[1].equals("06") || strArr[1].equals("6")))
        {
            Toast.makeText(MainActivity.this, "Trigger success at 6 sec position.......", Toast.LENGTH_SHORT).show();
            tvAutoSave.setVisibility(View.VISIBLE);
            tvAutoSave.startAnimation(animFadeIn);
        }

        int progress = vidView.getCurrentPosition() * 100 / vidView.getDuration();
        videoProgress.setProgress(progress);

        tvCurrentTime.setText(""+currentPosition);
    }

    String msToTimeConverter(int millis)
    {
        return String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
    }

    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
            case R.id.tvAutoSave:
                tvAutoSave.setVisibility(View.GONE);
                tvAutoSave.startAnimation(animFadeOut);
                Toast.makeText(MainActivity.this, "Offer(s) saved in wallet successfully", Toast.LENGTH_SHORT).show();
                break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dny*_*h M 2

最后我得到了解决方案。以下是实现相同内容的步骤——

步骤 1] 在“res/values/”文件夹中创建一个“attrs.xml”文件,并将以下代码粘贴到该文件中--

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DottedSeekBar">
        <attr name="dots_positions" format="reference"/>
        <attr name="dots_drawable" format="reference"/>
    </declare-styleable>
</resources>
Run Code Online (Sandbox Code Playgroud)

步骤2]准备一个要用于在进度条上标记的图像图标,并将其命名为“video_mark.png”。

Step-3]创建一个自定义SeekBar,如下所示--

public class DottedSeekBar extends AppCompatSeekBar {

    /** Int values which corresponds to dots */
    private int[] mDotsPositions = null;
    /** Drawable for dot */
    private Bitmap mDotBitmap = null;

    public DottedSeekBar(final Context context) {
        super(context);
        init(null);
    }

    public DottedSeekBar(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public DottedSeekBar(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }

    /**
     * Initializes Seek bar extended attributes from xml
     *
     * @param attributeSet {@link AttributeSet}
     */
    private void init(final AttributeSet attributeSet) {
        final TypedArray attrsArray = getContext().obtainStyledAttributes(attributeSet, R.styleable.DottedSeekBar, 0, 0);

        final int dotsArrayResource = attrsArray.getResourceId(R.styleable.DottedSeekBar_dots_positions, 0);

        if (0 != dotsArrayResource) {
            mDotsPositions = getResources().getIntArray(dotsArrayResource);
        }

        final int dotDrawableId = attrsArray.getResourceId(R.styleable.DottedSeekBar_dots_drawable, 0);

        if (0 != dotDrawableId) {
            mDotBitmap = BitmapFactory.decodeResource(getResources(), dotDrawableId);
        }
    }

    /**
     * @param dots to be displayed on this SeekBar
     */
    public void setDots(final int[] dots) {
        mDotsPositions = dots;
        invalidate();
    }

    /**
     * @param dotsResource resource id to be used for dots drawing
     */
    public void setDotsDrawable(final int dotsResource)
    {
        mDotBitmap = BitmapFactory.decodeResource(getResources(), dotsResource);
        invalidate();
    }

    @Override
    protected synchronized void onDraw(final Canvas canvas) {
        super.onDraw(canvas);

        final float width=getMeasuredWidth()-getPaddingLeft()-getPaddingRight();
        final float step=width/(float)(getMax());

        if (null != mDotsPositions && 0 != mDotsPositions.length && null != mDotBitmap) {
            // draw dots if we have ones
            for (int position : mDotsPositions) {
                canvas.drawBitmap(mDotBitmap, position * step, 0, null);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

步骤 4] 在您的 Activity.xml 文件中使用此自定义 SeekBar,如下所示 -

<com.your_package.DottedSeekBar
                        android:id="@+id/videoProgress"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"/>                    
Run Code Online (Sandbox Code Playgroud)

步骤5]在“Activity.java”类的“onCreate()”方法中添加以下代码--

        DottedSeekBar videoProgress = (DottedSeekBar) findViewById(R.id.videoProgress);
        // Disable SeekBar Thumb Drag. (Optional)
                videoProgress.setOnTouchListener(new View.OnTouchListener()
                {
                    @Override
                    public boolean onTouch(View view, MotionEvent motionEvent)
                    {
                        return true;
                    }
                });


    // Set custom thumb icon color here (Optional)

        videoProgress.getThumb().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);

    // Add below line to avoid unnecessary SeekBar padding. (Optional)

        videoProgress.setPadding(0, 0, 0, 0);

// Handler to update video progress time--

handler = new Handler();
        // Define the code block to be executed
        final Runnable runnableCode = new Runnable() {
            @Override
            public void run()
            {
                updateCurrentTime();
                // Repeat this the same runnable code block again another 1 seconds
                // 'this' is referencing the Runnable object
                handler.postDelayed(this, 1000);
            }
        };

Use "videoView.setOnPreparedListener()" method to calculate total video time in seconds



     yourVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
                                              {
                                                  @Override
                                                  public void onPrepared(MediaPlayer mp)
                                                  {


                                                      String strTotalDuration = msToTimeConverter(vidView.getDuration());

                                                      String[] strTimeArr = strTotalDuration.split(":");

                                                      int min = Integer.parseInt(strTimeArr[0]);
                                                      int videoLengthInSec = Integer.parseInt(strTimeArr[1]);
                                                      videoLengthInSec = videoLengthInSec + (min*60);

                                                      videoProgress.setProgress(0);
                                                      videoProgress.setMax(videoLengthInSec);

                                                      // Start the initial runnable task by posting through the handler
                                                      handler.post(runnableCode);

                                                      initVideoMarkers();
                                                  }
                                              }

                );
Run Code Online (Sandbox Code Playgroud)

步骤 6] 在“Activity.java”类中复制以下所需方法--

// 更新时间进度的方法

 private void updateCurrentTime()
        {
            if (videoProgress.getProgress() >= 100)
            {
                handler.removeMessages(0);
            }
            String currentPosition = msToTimeConverter(vidView.getCurrentPosition());

            String[] strArr = currentPosition.split(":");

            int progress = vidView.getCurrentPosition() * videoLengthInSec / vidView.getDuration();

            videoProgress.setProgress(progress);
        }

// Milliseconds to Time converter Method

     String msToTimeConverter(int millis)
        {
            return String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                    TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
        }
Run Code Online (Sandbox Code Playgroud)

// 设置Marker值的方法

private void initVideoMarkers()
        {
            // Here I'm adding markers on 10, 15 and 20 Second index
            videoProgress.setDots(new int[] {10, 15, 20});
            videoProgress.setDotsDrawable(R.drawable.video_mark);
       }
Run Code Online (Sandbox Code Playgroud)