有什么方法可以在某个位置用不同的颜色标记 ProgressBar 或 SeekBar,就像 "Youtube" 广告标记一样?

Is there any way to mark ProgressBar OR SeekBar at some position with different color just like "Youtube" Ad marker?

实际上我在我的应用程序中实现了自定义视频播放器,我还使用 SeekBar View 显示视频进度。现在我想在我的视频进度条上显示一些标记,例如 "Youtube" 广告标记,标记的数量及其各自的 position/index 将在运行时决定。我发现这个问题()之前在Whosebug上问过,但不幸的是还没有解决方案。请查看下图以了解我想要实现的目标。

https://drive.google.com/open?id=1qxfsTu8WOPMIlek7616rVQgzab8CFVcp

非常感谢任何帮助。谢谢。

你好@PKMBSD 我知道已经很晚了,但请查看下面的答案,这肯定会帮助你实现你想要的--

Step-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>

Step-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);
            }
        }
    }
}

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

<com.your_package.DottedSeekBar
                    android:id="@+id/videoProgress"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

Step-5] 在 "Activity.java" class--

的 "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 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 = 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);
            }
        };

 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();
                                          }
                                      }

        );

第 6 步] 将以下所需方法复制到 "Activity.java" class--

//更新时间进度的方法

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);
    }

// 毫秒到时间转换器方法

 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)));
    }

//设置标记值的方法

  private void initVideoMarkers()
        {
            videoProgress.setDots(new int[] {10, 15, 20});
            videoProgress.setDotsDrawable(R.drawable.video_mark);
       }

我遇到了同样的挑战,我正在使用这个解决方案,它 100% 正常工作。希望对你有帮助。