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)
最后我得到了解决方案。以下是实现相同内容的步骤——
步骤 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)
| 归档时间: |
|
| 查看次数: |
206 次 |
| 最近记录: |