一个可以实时显示进度的自定义view,类似于listview中音乐播放背景变化的效果

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


  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值