Android 自定义View 横向翻页
16lz
2021-01-23
原理见:翻页效果原理实现之翻页的尝试
package com.stone.turnpage.view;import android.content.Context;import android.content.res.Configuration;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.os.Handler;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.widget.Toast;import java.util.ArrayList;import java.util.List;/** * author : stone * email : aa86799@163.com * time : 16/7/8 10 35 */public class HorizonTurnPageView extends View { private List mBitmaps; private float mClipX; //裁剪右端点坐标 private float mCurPointX;// 指尖触碰屏幕时点X的坐标值 private float mAutoAreaLeft, mAutoAreaRight; //控件左侧和右侧自动吸附的区域 private boolean mIsLastPage; //是否最后一页 private boolean mIsNextPage; //是否下一页 private int mPageIndex; private Runnable mMsgCallback; private Handler mHandler = new Handler(); public HorizonTurnPageView(Context context) { super(context);// ViewConfiguration.get(context).getScaledTouchSlop() } public void setBitmaps(List bitmaps) { if (null == bitmaps || bitmaps.size() == 0) return; this.mBitmaps = bitmaps; System.out.println("setBitmaps"); invalidate(); } /** * 图片倒序:集合中最先加入的图(最后绘制)就能绘制在最上层 */ private void initBitmaps() { if (mBitmaps == null) { return; } List temp = new ArrayList(); for (int i = mBitmaps.size() - 1; i >= 0; i--) { Bitmap bitmap = Bitmap.createScaledBitmap(mBitmaps.get(i), getWidth(), getHeight(), true); temp.add(bitmap); } mBitmaps = temp; } private void drawBitmaps(Canvas canvas) {/* for (int i = 0; i < mBitmaps.size(); i++) {// canvas.save(); if (i == mBitmaps.size() - 1) {//只有最后一位的图片(即原集合中的首图)时才裁剪一次 canvas.clipRect(0, 0, mClipX, getHeight()); } canvas.drawBitmap(mBitmaps.get(i), 0, 0, null);// canvas.restore(); }*/ /* 如果图片太多,那么 其实只要绘制上下两张图即可, 而不用 所有都绘制 代码重构如下 */ mIsLastPage = false; mPageIndex = mPageIndex < 0 ? 0 : mPageIndex; mPageIndex = mPageIndex > mBitmaps.size() ? mBitmaps.size() : mPageIndex; // 计算数据起始位置 int start = mBitmaps.size() - 2 - mPageIndex;//mBitmaps.size() - 2 表示倒数第二个 int end = mBitmaps.size() - mPageIndex; // end - start = 2 /* * 如果数据起点位置小于0则表示当前已经到了最后一张图片 */ if (start < 0) { mIsLastPage = true; // 此时mPageIndex = size - 1 showToast("已经最后一页了"); // 强制重置起始位置 start = 0; end = 1; } for (int i = start; i < end; i++) {//end - start = 2 这里最多循环两次 if (!mIsLastPage && i == end - 1) { canvas.clipRect(0, 0, mClipX, getHeight()); //之后的绘制会相对当前裁剪区 } canvas.drawBitmap(mBitmaps.get(i), 0, 0, null); } } @Override public boolean onTouchEvent(MotionEvent event) { mIsNextPage = true; switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mCurPointX = event.getX(); if (mCurPointX < mAutoAreaLeft) { mIsNextPage = false; //上一页 mPageIndex--; mClipX = mCurPointX; invalidate(); } break; case MotionEvent.ACTION_MOVE: mClipX = event.getX(); invalidate(); break; case MotionEvent.ACTION_UP: judgeSlideAuto(); /* * 如果当前页不是最后一页 * 如果是需要翻下一页 * 并且上一页已被clip掉,即judgeSlideAuto中执行了向左 */ if (!mIsLastPage && mIsNextPage && mClipX <= 0) { mPageIndex++; mClipX = getWidth(); invalidate(); } break; } return true; } /** * 判断是否要自动滑动: 向左或向右 滑动到底 */ private void judgeSlideAuto() { if (mClipX < mAutoAreaLeft) {// 小于 1/5 w 向左 while (mClipX > 0) { mClipX--; invalidate(); } } else if (mClipX > mAutoAreaRight) {// 大于 4/5 w 向右 while (mClipX < getWidth()) { mClipX++; invalidate(); } } } /* onMeasure后 调用, 如果是ViewGroup型, 在onLayout时又改变了大小才会 再次调用 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); System.out.println("onSizeChanged"); initBitmaps(); mClipX = getWidth(); mAutoAreaLeft = getWidth() / 5f; mAutoAreaRight = getWidth() / 5f * 4; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (null == mBitmaps || mBitmaps.size() == 0) { return; } drawBitmaps(canvas); } private void showToast(final Object msg) { mHandler.removeCallbacksAndMessages(null); mMsgCallback = new Runnable() { @Override public void run() { Toast.makeText(getContext(), msg.toString(), Toast.LENGTH_SHORT).show(); } }; mHandler.postDelayed(mMsgCallback, 200); }}
我的自定义View项目地址: https://github.com/aa86799/MyCustomView (欢迎start&fork)
本文地址:https://github.com/aa86799/MyCustomView/tree/master/turnpage
更多相关文章
- Android 实现图片轮播的三种方法
- android 设置 dialog位置
- Android 手势滑动,多点触摸放大缩小图片
- android 图片压缩的方法
- android中wifi原理及流程分析
- ArcGIS for Android 离线数据编辑原理
- Android有效解决加载大图片时内存溢出的问题
- RelativeLayout里常用的位置属性