实现效果
看到这个效果,看到很多人用ViewFlipper实现,但是效果并不理想,于是我想到用RecyclerView试试。
主要是监听recyclerView滑动,开始和暂停来控制,废话不多说,上代码。
自定义RecyclerView
public class AutoPollRecyclerViewextends RecyclerView {
private static final long TIME_AUTO_POLL =16;
private static final long TIME_AUTO_POLL_1 =2000;
AutoPollTaskautoPollTask;
AutoPollTask1autoPollTask1;
private int index =0;
private boolean running; //标示是否正在自动轮询
private boolean canRun;//标示是否可以自动轮询,可在不需要的是否置false
private final int mTouchSlop;
public AutoPollRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
// autoPollTask = new AutoPollTask(this);
autoPollTask1 =new AutoPollTask1(this);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
/**
* 持续滑动(走马灯)
*/
static class AutoPollTaskimplements Runnable {
private final WeakReferencemReference;
//使用弱引用持有外部类引用->防止内存泄漏
public AutoPollTask(AutoPollRecyclerView reference) {
this.mReference =new WeakReference(reference);
}
@Override
public void run() {
Log.e("AutoPollRecyclerView", System.currentTimeMillis() +"");
AutoPollRecyclerView recyclerView =mReference.get();
if (recyclerView !=null && recyclerView.running && recyclerView.canRun) {
recyclerView.scrollBy(2, 2);
recyclerView.postDelayed(recyclerView.autoPollTask, recyclerView.TIME_AUTO_POLL);
}
}
}
/***
* 一次只能滑一个item(轮播图)
*/
static class AutoPollTask1implements Runnable {
private final WeakReferencemReference;
//使用弱引用持有外部类引用->防止内存泄漏
public AutoPollTask1(AutoPollRecyclerView reference) {
this.mReference =new WeakReference(reference);
}
@Override
public void run() {
AutoPollRecyclerView recyclerView =mReference.get();
if (recyclerView !=null && recyclerView.running && recyclerView.canRun) {
recyclerView.smoothScrollToPosition(++recyclerView.index);
recyclerView.postDelayed(recyclerView.autoPollTask1, TIME_AUTO_POLL_1);
}
}
}
//开启:如果正在运行,先停止->再开启
public void start() {
if (running)
stop();
canRun =true;
running =true;
// postDelayed(autoPollTask,TIME_AUTO_POLL);
postDelayed(autoPollTask1, TIME_AUTO_POLL_1);
}
public void stop() {
running =false;
// removeCallbacks(autoPollTask);
removeCallbacks(autoPollTask1);
}
//取消RecyclerView的惯性,使每次手动只能滑一个
int lastY =0;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
lastY = (int) ev.getRawY();
if (running)
stop();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
int nowY = (int) ev.getRawY();
if (nowY -lastY >mTouchSlop) {//向下滑动
smoothScrollToPosition(index ==0 ?0 : --index);
if (canRun)
start();
return true;
}else if (lastY - nowY >mTouchSlop) {//向上滑动
smoothScrollToPosition(++index);
if (canRun)
start();
return true;
}
break;
}
return super.dispatchTouchEvent(ev);
}
// 实现渐变效果
PaintmPaint;
private int layerId;
private LinearGradientlinearGradient;
private int preWidth =0;// Recyclerview宽度动态变化时,监听每一次的宽度
public void doTopGradualEffect(final int itemViewWidth) {
mPaint =new Paint();
// dst_in 模式,实现底层透明度随上层透明度进行同步显示(即上层为透明时,下层就透明,并不是上层覆盖下层)
final Xfermode xfermode =new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
mPaint.setXfermode(xfermode);
addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(canvas, parent, state);
// 当linearGradient为空即第一次绘制 或 Recyclerview宽度发生改变时,重新计算透明位置
if (linearGradient ==null ||preWidth != parent.getWidth()) {
// 透明位置从最后一个 itemView 的一半处到 Recyclerview 的最右边
linearGradient =new LinearGradient(parent.getWidth() - (itemViewWidth /2), 0.0f, parent.getWidth(), 0.0f, new int[]{Color.BLACK, 0}, null, Shader.TileMode.CLAMP);
preWidth = parent.getWidth();
}
mPaint.setXfermode(xfermode);
mPaint.setShader(linearGradient);
canvas.drawRect(0.0f, 0.0f, parent.getRight(), parent.getBottom(), mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
// 此处 Paint的参数这里传的null, 在传入 mPaint 时会出现第一次打开黑屏闪现的问题
// 注意 saveLayer 不能省也不能移动到onDrawOver方法里
layerId = c.saveLayer(0.0f, 0.0f, (float) parent.getWidth(), (float) parent.getHeight(), null, Canvas.ALL_SAVE_FLAG);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// 该方法作用自行百度
super.getItemOffsets(outRect, view, parent, state);
}
});
}
}
自定义Manger控制滑动速度
/**
* 控制滑动速度的LinearLayoutManager
*/
public class ScrollSpeedLinearLayoutMangerextends
LinearLayoutManager {
private float MILLISECONDS_PER_INCH =0.03f;
private Contextcontxt;
public ScrollSpeedLinearLayoutManger(Context context) {
super(context);
this.contxt = context;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller =
new LinearSmoothScroller(recyclerView.getContext()) {
@Override
public PointFcomputeScrollVectorForPosition(int targetPosition) {
return ScrollSpeedLinearLayoutManger.this
.computeScrollVectorForPosition(targetPosition);
}
//This returns the milliseconds it takes to
//scroll one pixel.
@Override
protected float calculateSpeedPerPixel
(DisplayMetrics displayMetrics) {
setSpeedSlow();
return MILLISECONDS_PER_INCH / displayMetrics.density;
// return 700;
//返回滑动一个pixel需要多少毫秒
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
public void setSpeedSlow() {
//自己在这里用density去乘,希望不同分辨率设备上滑动速度相同
//0.3f是自己估摸的一个值,可以根据不同需求自己修改
MILLISECONDS_PER_INCH =contxt.getResources().getDisplayMetrics().density *3f;
}
public void setSpeedFast() {
MILLISECONDS_PER_INCH =contxt.getResources().getDisplayMetrics().density *0.03f;
}
}
自定义Adapter
public class AutoPollAdapterextends RecyclerView.Adapter {
/**
* 事件回调监听
*/
private OnItemClickListeneronItemClickListener;
private Contextcontext;
private ListlistBeans;
public AutoPollAdapter(Context context, List listBeans) {
this.context = context;
this.listBeans = listBeans;
}
@Override
public ViewHolderonCreateViewHolder(ViewGroup parent, int viewType) {
// 实例化展示的view
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_auto_poll, parent, false);
// 实例化viewholder
ViewHolder viewHolder =new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.tvName.setText(listBeans.get(position %listBeans.size()));
holder.tvComment.setText("用户评论" + position);
}
@Override
public int getItemCount() {
//主要在这,实现无线轮播效果
return Integer.MAX_VALUE;
}
public static class ViewHolderextends RecyclerView.ViewHolder {
@BindView(R.id.simple_header)
SimpleDraweeViewsimpleCover;
@BindView(R.id.tv_name)
TextViewtvName;
@BindView(R.id.tv_comment)
TextViewtvComment;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
/**
* 设置回调监听
*
* @param listener
*/
public void setOnItemClickListener(OnItemClickListener listener) {
this.onItemClickListener = listener;
}
public interface OnItemClickListener {
void onItemClick(int position);
}
}
布局是很简单的就不贴了
使用方法
在Acitivity中使用
ScrollSpeedLinearLayoutManger layoutManager =new ScrollSpeedLinearLayoutManger(this);
layoutManager.setSmoothScrollbarEnabled(true);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);// 布局管理器。
recyclerView.setHasFixedSize(true);// 如果Item够简单,高度是确定的,打开FixSize将提高性能。
recyclerView.setItemAnimator(new DefaultItemAnimator());// 设置Item默认动画,加也行,不加也行。
recyclerView.setAdapter(new AutoPollAdapter(TestActivity.this, list));
recyclerView.start();
recyclerView.doTopGradualEffect(StringUtil.ScreenWidth(this));
好了,到此结束,点个赞再走呗...
欢迎大家进群探讨Android相关技术 群号:548154942