有什么方法可以在某个位置用不同的颜色标记 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% 正常工作。希望对你有帮助。
实际上我在我的应用程序中实现了自定义视频播放器,我还使用 SeekBar View 显示视频进度。现在我想在我的视频进度条上显示一些标记,例如 "Youtube" 广告标记,标记的数量及其各自的 position/index 将在运行时决定。我发现这个问题(
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% 正常工作。希望对你有帮助。