一个可以实时显示进度的自定义view,类似于listview中音乐播放背景变化的效果
2016-01-17 18:50
585 查看
package progresslayoutdemo.wjj.com.progresslayoutdemo;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Animatable;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
public class ProgressLayout extends View implements Animatable {
private static final int COLOR_EMPTY_DEFAULT = 0x00000000;
private static final int COLOR_LOADED_DEFAULT = 0x11FFFFFF;
private static final int PROGRESS_SECOND_MS = 1000;
private static Paint paintProgressLoaded;
private static Paint paintProgressEmpty;
private boolean isPlaying = false;
private boolean isAutoProgress;
private int mHeight;
private int mWidth;
private int maxProgress;
private int currentProgress = 0;
private Handler handlerProgress;
private ProgressLayoutListener progressLayoutListener;
public ProgressLayout(Context context) {
this(context, null);
}
public ProgressLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ProgressLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
@Override public boolean isRunning() {
return isPlaying;
}
@Override public void start() {
if (isAutoProgress) {
isPlaying = true;
handlerProgress.removeCallbacksAndMessages(null);
handlerProgress.postDelayed(mRunnableProgress, 0);
}
}
@Override public void stop() {
isPlaying = false;
handlerProgress.removeCallbacks(mRunnableProgress);
postInvalidate();
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(0, 0, mWidth, mHeight, paintProgressEmpty);
canvas.drawRect(0, 0, calculatePositionIndex(currentProgress), mHeight, paintProgressLoaded);
}
private void init(Context context, AttributeSet attrs) {
setWillNotDraw(false);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.progressLayout);
isAutoProgress = a.getBoolean(R.styleable.progressLayout_autoProgress, true);
maxProgress = a.getInt(R.styleable.progressLayout_maxProgress, 0);
maxProgress = maxProgress * 10;
int loadedColor = a.getColor(R.styleable.progressLayout_loadedColor, COLOR_LOADED_DEFAULT);
int emptyColor = a.getColor(R.styleable.progressLayout_emptyColor, COLOR_EMPTY_DEFAULT);
a.recycle();
paintProgressEmpty = new Paint();
paintProgressEmpty.setColor(emptyColor);
paintProgressEmpty.setStyle(Paint.Style.FILL);
paintProgressEmpty.setAntiAlias(true);
paintProgressLoaded = new Paint();
paintProgressLoaded.setColor(loadedColor);
paintProgressLoaded.setStyle(Paint.Style.FILL);
paintProgressLoaded.setAntiAlias(true);
handlerProgress = new Handler();
}
private int calculatePositionIndex(int currentProgress) {
return (currentProgress * mWidth) / maxProgress;
}
public boolean isPlaying() {
return isPlaying;
}
public void cancel() {
isPlaying = false;
currentProgress = 0;
handlerProgress.removeCallbacks(mRunnableProgress);
postInvalidate();
}
public void setCurrentProgress(int currentProgress) {
this.currentProgress = currentProgress * 10;
postInvalidate();
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress * 10;
postInvalidate();
}
public void setAutoProgress(boolean isAutoProgress) {
this.isAutoProgress = isAutoProgress;
}
public void setProgressLayoutListener(ProgressLayoutListener progressLayoutListener) {
this.progressLayoutListener = progressLayoutListener;
}
private final Runnable mRunnableProgress = new Runnable() {
@Override public void run() {
if (isPlaying) {
if (currentProgress == maxProgress) {
if (progressLayoutListener != null) {
progressLayoutListener.onProgressCompleted();
}
currentProgress = 0;
setCurrentProgress(currentProgress);
stop();
} else {
postInvalidate();
currentProgress += 1;
if (progressLayoutListener != null) {
progressLayoutListener.onProgressChanged(currentProgress / 10);
}
handlerProgress.postDelayed(mRunnableProgress, PROGRESS_SECOND_MS / 10);
}
}
}
};
}
package progresslayoutdemo.wjj.com.progresslayoutdemo;
import android.os.Handler;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
public class RecylerListAdapter extends RecyclerView.Adapter<RecylerListAdapter.ViewHolder> {
/**
* 数据源集合
*/
private List<Track> trackList;
/**
* 当前播放的对象。
*/
private Track currentTrack;
/**
* 持续时间
*/
private int currentDuration = 0;
/**
* 是否正在播放
*/
private boolean isPlaying = false;
private static final int SECOND_MS = 1000;
/**
* recyclerview中调用的Handle
*/
private Handler mHandler = new Handler();
/**
* 计算秒数
*
*/
private final Runnable mRunnable = new Runnable() {
@Override public void run() {
currentDuration += 1;
mHandler.postDelayed(mRunnable, SECOND_MS);
}
};
/**
* 传参
*/
public void setTrackList(List<Track> trackList) {
this.trackList = trackList;
notifyDataSetChanged();
}
/**
* 创建holder
*/
@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view =
LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
/**
* 绑定对象
*/
@Override public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
final Track track = trackList.get(i);
viewHolder.textViewDuration.setText(calculateSongDuration(track.getDurationInSec()));
viewHolder.textViewSong.setText(track.getSongName());
viewHolder.textViewSinger.setText(track.getSingerName());
viewHolder.imageViewAction.setBackgroundResource(R.drawable.play);
viewHolder.progressLayout.setMaxProgress(track.getDurationInSec());
if (currentTrack != null && currentTrack == track) {
viewHolder.imageViewAction.setBackgroundResource(
isPlaying ? R.drawable.pause : R.drawable.play);
viewHolder.progressLayout.setCurrentProgress(currentDuration);
if (isPlaying) viewHolder.progressLayout.start();
} else {
viewHolder.progressLayout.cancel();
}
viewHolder.imageViewAction.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
if (track != currentTrack) {
currentTrack = track;
mHandler.removeCallbacks(mRunnable);
currentDuration = 0;
}
if (!viewHolder.progressLayout.isPlaying()) {
isPlaying = true;
viewHolder.progressLayout.start();
mHandler.postDelayed(mRunnable, 0);
viewHolder.imageViewAction.setBackgroundResource(R.drawable.pause);
notifyDataSetChanged();
} else {
isPlaying = false;
viewHolder.progressLayout.stop();
mHandler.removeCallbacks(mRunnable);
viewHolder.imageViewAction.setBackgroundResource(R.drawable.play);
notifyDataSetChanged();
}
}
});
/*
* 播放按钮的监听事件
* */
viewHolder.progressLayout.setProgressLayoutListener(new ProgressLayoutListener() {
@Override public void onProgressCompleted() {
viewHolder.imageViewAction.setBackgroundResource(R.drawable.play);
}
@Override public void onProgressChanged(int seconds) {
viewHolder.textViewDuration.setText(calculateSongDuration(seconds));
}
});
}
/**
* List大小
*/
@Override public int getItemCount() {
return trackList.size();
}
/**
* 换成分钟
*/
private String calculateSongDuration(int seconds) {
return new StringBuilder(String.valueOf(seconds / 60))
.append(":")
.append(String.valueOf(seconds % 60))
.toString();
}
/**
* ViewHolder对象
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.imageviewAction) ImageView imageViewAction;
@Bind(R.id.progressLayout) ProgressLayout progressLayout;
@Bind(R.id.textviewSong) TextView textViewSong;
@Bind(R.id.textviewSinger) TextView textViewSinger;
@Bind(R.id.textviewDuration) TextView textViewDuration;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Animatable;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
public class ProgressLayout extends View implements Animatable {
private static final int COLOR_EMPTY_DEFAULT = 0x00000000;
private static final int COLOR_LOADED_DEFAULT = 0x11FFFFFF;
private static final int PROGRESS_SECOND_MS = 1000;
private static Paint paintProgressLoaded;
private static Paint paintProgressEmpty;
private boolean isPlaying = false;
private boolean isAutoProgress;
private int mHeight;
private int mWidth;
private int maxProgress;
private int currentProgress = 0;
private Handler handlerProgress;
private ProgressLayoutListener progressLayoutListener;
public ProgressLayout(Context context) {
this(context, null);
}
public ProgressLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ProgressLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
@Override public boolean isRunning() {
return isPlaying;
}
@Override public void start() {
if (isAutoProgress) {
isPlaying = true;
handlerProgress.removeCallbacksAndMessages(null);
handlerProgress.postDelayed(mRunnableProgress, 0);
}
}
@Override public void stop() {
isPlaying = false;
handlerProgress.removeCallbacks(mRunnableProgress);
postInvalidate();
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(0, 0, mWidth, mHeight, paintProgressEmpty);
canvas.drawRect(0, 0, calculatePositionIndex(currentProgress), mHeight, paintProgressLoaded);
}
private void init(Context context, AttributeSet attrs) {
setWillNotDraw(false);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.progressLayout);
isAutoProgress = a.getBoolean(R.styleable.progressLayout_autoProgress, true);
maxProgress = a.getInt(R.styleable.progressLayout_maxProgress, 0);
maxProgress = maxProgress * 10;
int loadedColor = a.getColor(R.styleable.progressLayout_loadedColor, COLOR_LOADED_DEFAULT);
int emptyColor = a.getColor(R.styleable.progressLayout_emptyColor, COLOR_EMPTY_DEFAULT);
a.recycle();
paintProgressEmpty = new Paint();
paintProgressEmpty.setColor(emptyColor);
paintProgressEmpty.setStyle(Paint.Style.FILL);
paintProgressEmpty.setAntiAlias(true);
paintProgressLoaded = new Paint();
paintProgressLoaded.setColor(loadedColor);
paintProgressLoaded.setStyle(Paint.Style.FILL);
paintProgressLoaded.setAntiAlias(true);
handlerProgress = new Handler();
}
private int calculatePositionIndex(int currentProgress) {
return (currentProgress * mWidth) / maxProgress;
}
public boolean isPlaying() {
return isPlaying;
}
public void cancel() {
isPlaying = false;
currentProgress = 0;
handlerProgress.removeCallbacks(mRunnableProgress);
postInvalidate();
}
public void setCurrentProgress(int currentProgress) {
this.currentProgress = currentProgress * 10;
postInvalidate();
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress * 10;
postInvalidate();
}
public void setAutoProgress(boolean isAutoProgress) {
this.isAutoProgress = isAutoProgress;
}
public void setProgressLayoutListener(ProgressLayoutListener progressLayoutListener) {
this.progressLayoutListener = progressLayoutListener;
}
private final Runnable mRunnableProgress = new Runnable() {
@Override public void run() {
if (isPlaying) {
if (currentProgress == maxProgress) {
if (progressLayoutListener != null) {
progressLayoutListener.onProgressCompleted();
}
currentProgress = 0;
setCurrentProgress(currentProgress);
stop();
} else {
postInvalidate();
currentProgress += 1;
if (progressLayoutListener != null) {
progressLayoutListener.onProgressChanged(currentProgress / 10);
}
handlerProgress.postDelayed(mRunnableProgress, PROGRESS_SECOND_MS / 10);
}
}
}
};
}
package progresslayoutdemo.wjj.com.progresslayoutdemo;
import android.os.Handler;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
public class RecylerListAdapter extends RecyclerView.Adapter<RecylerListAdapter.ViewHolder> {
/**
* 数据源集合
*/
private List<Track> trackList;
/**
* 当前播放的对象。
*/
private Track currentTrack;
/**
* 持续时间
*/
private int currentDuration = 0;
/**
* 是否正在播放
*/
private boolean isPlaying = false;
private static final int SECOND_MS = 1000;
/**
* recyclerview中调用的Handle
*/
private Handler mHandler = new Handler();
/**
* 计算秒数
*
*/
private final Runnable mRunnable = new Runnable() {
@Override public void run() {
currentDuration += 1;
mHandler.postDelayed(mRunnable, SECOND_MS);
}
};
/**
* 传参
*/
public void setTrackList(List<Track> trackList) {
this.trackList = trackList;
notifyDataSetChanged();
}
/**
* 创建holder
*/
@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view =
LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
/**
* 绑定对象
*/
@Override public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
final Track track = trackList.get(i);
viewHolder.textViewDuration.setText(calculateSongDuration(track.getDurationInSec()));
viewHolder.textViewSong.setText(track.getSongName());
viewHolder.textViewSinger.setText(track.getSingerName());
viewHolder.imageViewAction.setBackgroundResource(R.drawable.play);
viewHolder.progressLayout.setMaxProgress(track.getDurationInSec());
if (currentTrack != null && currentTrack == track) {
viewHolder.imageViewAction.setBackgroundResource(
isPlaying ? R.drawable.pause : R.drawable.play);
viewHolder.progressLayout.setCurrentProgress(currentDuration);
if (isPlaying) viewHolder.progressLayout.start();
} else {
viewHolder.progressLayout.cancel();
}
viewHolder.imageViewAction.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
if (track != currentTrack) {
currentTrack = track;
mHandler.removeCallbacks(mRunnable);
currentDuration = 0;
}
if (!viewHolder.progressLayout.isPlaying()) {
isPlaying = true;
viewHolder.progressLayout.start();
mHandler.postDelayed(mRunnable, 0);
viewHolder.imageViewAction.setBackgroundResource(R.drawable.pause);
notifyDataSetChanged();
} else {
isPlaying = false;
viewHolder.progressLayout.stop();
mHandler.removeCallbacks(mRunnable);
viewHolder.imageViewAction.setBackgroundResource(R.drawable.play);
notifyDataSetChanged();
}
}
});
/*
* 播放按钮的监听事件
* */
viewHolder.progressLayout.setProgressLayoutListener(new ProgressLayoutListener() {
@Override public void onProgressCompleted() {
viewHolder.imageViewAction.setBackgroundResource(R.drawable.play);
}
@Override public void onProgressChanged(int seconds) {
viewHolder.textViewDuration.setText(calculateSongDuration(seconds));
}
});
}
/**
* List大小
*/
@Override public int getItemCount() {
return trackList.size();
}
/**
* 换成分钟
*/
private String calculateSongDuration(int seconds) {
return new StringBuilder(String.valueOf(seconds / 60))
.append(":")
.append(String.valueOf(seconds % 60))
.toString();
}
/**
* ViewHolder对象
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.imageviewAction) ImageView imageViewAction;
@Bind(R.id.progressLayout) ProgressLayout progressLayout;
@Bind(R.id.textviewSong) TextView textViewSong;
@Bind(R.id.textviewSinger) TextView textViewSinger;
@Bind(R.id.textviewDuration) TextView textViewDuration;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
相关文章推荐
- caffe训练测试自己的数据集
- 【牛腩新闻公布系统】WebForms UnobtrusiveValidationMode 须要“jquery”ScriptResourceMapping。
- 泛型(Generic)
- scull_p_read()函数分析
- 最长不降子序列(LIS)
- iOS开发调用相机拍摄多张照片
- iOS 真机测试
- (二)计算机网络体系结构与参考模型
- 恭喜自己获得了准博客专家
- Android Design Support Library(5)- CoordinatorLayout的入门使用
- 此博客停止更新
- LeetCode:Bulb Switcher
- libevent的安装
- JavaScript对象与JSON
- 代理总结
- 打印数值二进制形式
- gcc 编译参数 -fPIC 的详解和一些问题
- 随机森林算法的简单总结及python实现
- c++中的引用
- Linux 高性能server编程——高级I/O函数