如何在确切的给定时间索引处用不同颜色标记 SeekBar?
How to mark SeekBar with different color at exact given time index?
实际上我在我的应用程序中创建了一个自定义视频播放器,在这个应用程序中我使用 SeekBar 来显示视频进度。现在我试图在某个预定义的时间索引(例如 6 秒、20 秒和 50 秒)用不同的颜色标记 SeekBar,请查看下图以了解我到底想要什么--
我几乎完成了标记功能,但标记与准确的时间位置不匹配。请查看下面的图片以了解我的问题--
Image-1]
在此图像中,您可以清楚地看到当前 Thumb 位置正好是 6 秒。位置和第一个垂直蓝色标记实际上是我的 CustomSeekBar 标记 6 秒位置。
Image-2]
同理,在上图中你可以看到当前的Thumb位置正好是20秒。位置和第二个垂直蓝色标记实际上是我的 CustomSeekBar 标记 20 秒位置。
下面是我的“CustomSeekBar”class --
public class CustomSeekBar extends AppCompatSeekBar
{
private ArrayList<ProgressItem> mProgressItemsList;
public CustomSeekBar(Context context) {
super(context);
mProgressItemsList = new ArrayList<ProgressItem>();
}
public CustomSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSeekBar(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public void initData(ArrayList<ProgressItem> progressItemsList)
{
this.mProgressItemsList = progressItemsList;
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
protected void onDraw(Canvas canvas)
{
if (mProgressItemsList!=null && mProgressItemsList.size() > 0)
{
int progressBarWidth = getWidth();
int progressBarHeight = getHeight()+20;
int thumboffset = getThumbOffset()-20;
int lastProgressX = 0;
int progressItemWidth, progressItemRight;
for (int i = 0; i < mProgressItemsList.size(); i++)
{
ProgressItem progressItem = mProgressItemsList.get(i);
Paint progressPaint = new Paint();
progressPaint.setColor(getResources().getColor(
progressItem.color));
progressItemWidth = (int) (progressItem.progressItemPercentage
* progressBarWidth / 100);
progressItemRight = lastProgressX + progressItemWidth;
// for last item give right to progress item to the width
if (i == mProgressItemsList.size() - 1 && progressItemRight != progressBarWidth)
{
progressItemRight = progressBarWidth;
}
Rect progressRect = new Rect();
progressRect.set(lastProgressX, thumboffset / 2,
progressItemRight, progressBarHeight - thumboffset / 2);
canvas.drawRect(progressRect, progressPaint);
lastProgressX = progressItemRight;
}
super.onDraw(canvas);
}
}
}
下面是我的ProgressItemclass
public class ProgressItem
{
public int color;
public float progressItemPercentage;
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public float getProgressItemPercentage() {
return progressItemPercentage;
}
public void setProgressItemPercentage(float progressItemPercentage) {
this.progressItemPercentage = progressItemPercentage;
}
}
下面是我在 VideoActivity--
中的使用方式
CustomSeekBar videoProgress = (CustomSeekBar) findViewById(R.id.videoProgress);
// Disable SeekBar Thumb Drag.
videoProgress.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
return true;
}
});
/*videoProgress.getProgressDrawable().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);
videoProgress.getThumb().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);*/
videoProgress.getThumb().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);
videoProgress.setProgress(0);
videoProgress.setMax(100);
// Function to init markers
ArrayList<ProgressItem> progressItemList;
void initVideoProgressColor()
{
progressItemList = new ArrayList<ProgressItem>();
ProgressItem mProgressItem;
mProgressItem = new ProgressItem();
int vidDuration = vidView.getDuration();
mProgressItem.progressItemPercentage = 6;
Log.e("VideoActivity", mProgressItem.progressItemPercentage + "");
mProgressItem.color = R.color.transparent_clr;
progressItemList.add(mProgressItem);
// FIRST MARKER FOR 6-SEC. POSITION
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 0.5f;
mProgressItem.color = R.color.cerulean_blue;
progressItemList.add(mProgressItem);
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 20;
mProgressItem.color = R.color.transparent_clr;
progressItemList.add(mProgressItem);
// SECOND MARKER FOR 20-SEC. POSITION
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 0.5f;
mProgressItem.color = R.color.cerulean_blue;
progressItemList.add(mProgressItem);
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 70;
mProgressItem.color = R.color.transparent_clr;
progressItemList.add(mProgressItem);
videoProgress.initData(progressItemList);
videoProgress.invalidate();
}
有关更多详细信息,请查看下面的内容 link 我参考了它来实现此自定义 SeekBar-
https://www.androiddevelopersolutions.com/2015/01/android-custom-horizontal-progress-bar.html
此外,我尝试了下面 link 的解决方案,但不幸的是得到了相同的结果--
android seek bar customization,
实际上我已经很接近答案了,只是需要一个适当的指导,我想我会从你们这些专家那里得到。如果我可以提供更多详细信息,请告诉我。谢谢你。
终于找到解决办法了。以下是实施解决方案的步骤--
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;
}
});
// 在此处设置自定义缩略图图标颜色(可选)
videoProgress.getThumb().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);
// 添加下行以避免不必要的 SeekBar 填充。 (可选)
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);
}
};
使用"videoView.setOnPreparedListener()"方法计算总视频时间(以秒为单位)
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();
}
}
);
Step-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);
}
// 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)));
}
//设置标记值的方法
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);
}
实际上我在我的应用程序中创建了一个自定义视频播放器,在这个应用程序中我使用 SeekBar 来显示视频进度。现在我试图在某个预定义的时间索引(例如 6 秒、20 秒和 50 秒)用不同的颜色标记 SeekBar,请查看下图以了解我到底想要什么--
我几乎完成了标记功能,但标记与准确的时间位置不匹配。请查看下面的图片以了解我的问题--
Image-1]
在此图像中,您可以清楚地看到当前 Thumb 位置正好是 6 秒。位置和第一个垂直蓝色标记实际上是我的 CustomSeekBar 标记 6 秒位置。
Image-2]
同理,在上图中你可以看到当前的Thumb位置正好是20秒。位置和第二个垂直蓝色标记实际上是我的 CustomSeekBar 标记 20 秒位置。
下面是我的“CustomSeekBar”class --
public class CustomSeekBar extends AppCompatSeekBar
{
private ArrayList<ProgressItem> mProgressItemsList;
public CustomSeekBar(Context context) {
super(context);
mProgressItemsList = new ArrayList<ProgressItem>();
}
public CustomSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSeekBar(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public void initData(ArrayList<ProgressItem> progressItemsList)
{
this.mProgressItemsList = progressItemsList;
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
protected void onDraw(Canvas canvas)
{
if (mProgressItemsList!=null && mProgressItemsList.size() > 0)
{
int progressBarWidth = getWidth();
int progressBarHeight = getHeight()+20;
int thumboffset = getThumbOffset()-20;
int lastProgressX = 0;
int progressItemWidth, progressItemRight;
for (int i = 0; i < mProgressItemsList.size(); i++)
{
ProgressItem progressItem = mProgressItemsList.get(i);
Paint progressPaint = new Paint();
progressPaint.setColor(getResources().getColor(
progressItem.color));
progressItemWidth = (int) (progressItem.progressItemPercentage
* progressBarWidth / 100);
progressItemRight = lastProgressX + progressItemWidth;
// for last item give right to progress item to the width
if (i == mProgressItemsList.size() - 1 && progressItemRight != progressBarWidth)
{
progressItemRight = progressBarWidth;
}
Rect progressRect = new Rect();
progressRect.set(lastProgressX, thumboffset / 2,
progressItemRight, progressBarHeight - thumboffset / 2);
canvas.drawRect(progressRect, progressPaint);
lastProgressX = progressItemRight;
}
super.onDraw(canvas);
}
}
}
下面是我的ProgressItemclass
public class ProgressItem
{
public int color;
public float progressItemPercentage;
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public float getProgressItemPercentage() {
return progressItemPercentage;
}
public void setProgressItemPercentage(float progressItemPercentage) {
this.progressItemPercentage = progressItemPercentage;
}
}
下面是我在 VideoActivity--
中的使用方式CustomSeekBar videoProgress = (CustomSeekBar) findViewById(R.id.videoProgress);
// Disable SeekBar Thumb Drag.
videoProgress.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
return true;
}
});
/*videoProgress.getProgressDrawable().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);
videoProgress.getThumb().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);*/
videoProgress.getThumb().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);
videoProgress.setProgress(0);
videoProgress.setMax(100);
// Function to init markers
ArrayList<ProgressItem> progressItemList;
void initVideoProgressColor()
{
progressItemList = new ArrayList<ProgressItem>();
ProgressItem mProgressItem;
mProgressItem = new ProgressItem();
int vidDuration = vidView.getDuration();
mProgressItem.progressItemPercentage = 6;
Log.e("VideoActivity", mProgressItem.progressItemPercentage + "");
mProgressItem.color = R.color.transparent_clr;
progressItemList.add(mProgressItem);
// FIRST MARKER FOR 6-SEC. POSITION
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 0.5f;
mProgressItem.color = R.color.cerulean_blue;
progressItemList.add(mProgressItem);
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 20;
mProgressItem.color = R.color.transparent_clr;
progressItemList.add(mProgressItem);
// SECOND MARKER FOR 20-SEC. POSITION
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 0.5f;
mProgressItem.color = R.color.cerulean_blue;
progressItemList.add(mProgressItem);
mProgressItem = new ProgressItem();
mProgressItem.progressItemPercentage = 70;
mProgressItem.color = R.color.transparent_clr;
progressItemList.add(mProgressItem);
videoProgress.initData(progressItemList);
videoProgress.invalidate();
}
有关更多详细信息,请查看下面的内容 link 我参考了它来实现此自定义 SeekBar-
https://www.androiddevelopersolutions.com/2015/01/android-custom-horizontal-progress-bar.html
此外,我尝试了下面 link 的解决方案,但不幸的是得到了相同的结果-- android seek bar customization,
实际上我已经很接近答案了,只是需要一个适当的指导,我想我会从你们这些专家那里得到。如果我可以提供更多详细信息,请告诉我。谢谢你。
终于找到解决办法了。以下是实施解决方案的步骤--
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;
}
});
// 在此处设置自定义缩略图图标颜色(可选)
videoProgress.getThumb().setColorFilter(getResources().getColor(R.color.cerulean_blue), PorterDuff.Mode.SRC_IN);
// 添加下行以避免不必要的 SeekBar 填充。 (可选)
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);
}
};
使用"videoView.setOnPreparedListener()"方法计算总视频时间(以秒为单位)
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();
}
}
);
Step-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);
}
// 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)));
}
//设置标记值的方法
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);
}