Android 如何加载大图片
16lz
2021-01-23
第一步:创建手势基类:
public abstract class BaseGuestureDetector { /** 进行中的手势 */ protected boolean mIsGestureMoving; /** 先前的事件 */ protected MotionEvent mPreMotionEvent; /** 当前的事件 */ protected MotionEvent mCurrentMotionEvent; public Context mContext; public BaseGuestureDetector(Context context){ mContext = context; } public boolean onTouchEvent(MotionEvent event){ if (!mIsGestureMoving) { handleStartProgressEvent(event); }else { handleInProgressEvent(event); } return true; } protected abstract void handleInProgressEvent(MotionEvent event); protected abstract void handleStartProgressEvent(MotionEvent event); protected abstract void updateStateByEvent(MotionEvent event); protected void resetState(){ if (mPreMotionEvent != null) { mPreMotionEvent.recycle(); mPreMotionEvent = null; } if (mCurrentMotionEvent != null) { mCurrentMotionEvent.recycle(); mCurrentMotionEvent = null; } mIsGestureMoving = false; }}
第二步:根据基类创建手势类
public class MoveGestureDetector extends BaseGuestureDetector { /** 当前的手指位置 */ private PointF mCurrentPointF; /** 上次的手指位置 */ private PointF mPrePointF; /** 用于记录最终结果,并返回 */ private PointF mExtenalPointer = new PointF(); private OnMoveGestureListener mListener; public MoveGestureDetector(Context context, OnMoveGestureListener listener) { super(context); this.mListener = listener; } /** * 处理正在进行的动作 */ @Override protected void handleInProgressEvent(MotionEvent event) { int action = event.getAction() & MotionEvent.ACTION_MASK; switch (action) { // 手指弹起与离开时 case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mListener.onMoveEnd(this); resetState(); break; // 手指移动 case MotionEvent.ACTION_MOVE: updateStateByEvent(event); boolean move = mListener.onMove(this); if (move) { mPreMotionEvent.recycle(); mPreMotionEvent = MotionEvent.obtain(event); } break; default: break; } } /** * 处理开始的事件 */ @Override protected void handleStartProgressEvent(MotionEvent event) { int action = event.getAction() & MotionEvent.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN: // 防止没有接收到CANCEL or UP ,保险起见 resetState(); // 初始化 mPreMotionEvent = MotionEvent.obtain(event); updateStateByEvent(event); break; case MotionEvent.ACTION_MOVE: mIsGestureMoving = mListener.onMoveBegin(this); break; default: break; } } @Override protected void updateStateByEvent(MotionEvent event) { final MotionEvent prev = mPreMotionEvent; // 计算开始点的位置 mPrePointF = caculateFocalPointer(prev); mCurrentPointF = caculateFocalPointer(event); Log.e("TAG", mPrePointF.toString() + " , " + mCurrentPointF); // 是否跳过这个点,如果前后手指数不一样 boolean mSkipThisMoveEvent = prev.getPointerCount() != event.getPointerCount(); // 如果是无效的设置为0 mExtenalPointer.x = mSkipThisMoveEvent ? 0 : mCurrentPointF.x - mPrePointF.x; mExtenalPointer.y = mSkipThisMoveEvent ? 0 : mCurrentPointF.y - mPrePointF.y; } /** * 根据event计算多指中心点 * * @param event * @return */ private PointF caculateFocalPointer(MotionEvent event) { final int count = event.getPointerCount(); float x = 0, y = 0; for (int i = 0; i < count; i++) { x += event.getX(i); y += event.getY(i); } // 取手指的中心点 x = x / count; y = y / count; return new PointF(x, y); } /** * 向外暴露的两个方法,获得移动中的位置 * * @return */ public float getMoveX() { return mExtenalPointer.x; } public float getMoveY() { return mExtenalPointer.y; } /** * 回调函数 * * @Project App_View * @Package com.android.view.largeimageview * @author chenlin * @version 1.0 * @Note TODO */ public interface OnMoveGestureListener { /** * 手指开始移动 * * @param detector * @return */ public boolean onMoveBegin(MoveGestureDetector detector); /** * 手指移动中 * * @param detector * @return */ public boolean onMove(MoveGestureDetector detector); /** * 移动结束 * * @param detector */ public void onMoveEnd(MoveGestureDetector detector); } public static class SimpleMoveGestureDetector implements OnMoveGestureListener { @Override public boolean onMoveBegin(MoveGestureDetector detector) { return true; } @Override public boolean onMove(MoveGestureDetector detector) { return false; } @Override public void onMoveEnd(MoveGestureDetector detector) { } }}
第三步:自定义LargeImageView
public class LargeImageView extends View { /**图片的选择的区域 */ private BitmapRegionDecoder mDecoder; /**图片的宽度和高度 */ private int mImageWidth, mImageHeight; /**绘制的区域*/ private volatile Rect mRect = new Rect(); /**移动时手势*/ private MoveGestureDetector mDetector; /** * Creates Bitmap objects from various sources, including files, streams, * and byte-arrays. */ private static final BitmapFactory.Options options = new BitmapFactory.Options(); static{ /*设置让解码器以最佳方式解码*/ options.inPreferredConfig = Bitmap.Config.RGB_565; } public LargeImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public LargeImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public LargeImageView(Context context) { super(context); init(); } //初始化手势 private void init() { mDetector = new MoveGestureDetector(getContext(), new SimpleMoveGestureDetector(){ @Override public boolean onMove(MoveGestureDetector detector) { // 移动时 int moveX = (int) detector.getMoveX(); int moveY = (int) detector.getMoveY(); Logger.i("large", "moveX == " + moveX); Logger.i("large", "moveY == " + moveY); //如果图片的宽度>view的宽度 if (mImageWidth > getWidth()) { //向左移动 mRect.offset(-moveX, 0); checkWidth(); //重构 invalidate(); } if (mImageHeight > getHeight()) { //向上移动 mRect.offset(0, -moveY); checkHeight(); //重构 invalidate(); } return true; } }); }// private OnMoveGestureListener listener = new OnMoveGestureListener(){//// @Override// public boolean onMoveBegin(MoveGestureDetector detector) {// //Toast.makeText(getContext(), "开始移动", 1).show();// return false;// }//// @Override// public boolean onMove(MoveGestureDetector detector) {// // 移动时// int moveX = (int) detector.getMoveX();// int moveY = (int) detector.getMoveY();// //如果图片的宽度>view的宽度// if (mImageWidth > getWidth()) {// //向左移动// mRect.offset(-moveX, 0);// checkWidth();// //重构// invalidate();// }// if (mImageHeight > getHeight()) {// //向上移动// mRect.offset(0, -moveY);// checkHeight();// //重构// invalidate();// }// return true;// }//// @Override// public void onMoveEnd(MoveGestureDetector detector) {// //Toast.makeText(getContext(), "移动停止", 1).show();// }// // }; /** * 把图片的宽度归位 */ protected void checkWidth() { Rect rect = mRect; int width = mImageWidth; //图片的右边 > view if (rect.right > width) { rect.right = width; //左边 = 图片的宽度 - 视图宽度 rect.left = width - getWidth(); } //在屏幕外 if (rect.left < 0) { rect.left = 0; //右边 = 视图宽度 rect.right = getWidth(); } } /** * 图片的高度归位 */ protected void checkHeight() { Rect rect = mRect; int height = mImageHeight; if (rect.bottom > height) { rect.bottom = height; rect.top = height - getHeight(); } if (rect.top < 0) { rect.top = 0; rect.bottom = getHeight(); } } /** * 第一步:加载图片后,显示图片的中心位置 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //指的是视图的测量宽度 int widthMeasure = getMeasuredWidth(); int heightMeasure = getMeasuredHeight(); //图片实际的宽度 int imageWidth = mImageWidth; int imageHeight = mImageHeight; //默认直接显示图片的中心区域,可以自己去调节 mRect.left = (imageWidth - widthMeasure)/2; mRect.top = (imageHeight - heightMeasure)/2; mRect.right = mRect.left + widthMeasure; mRect.bottom = mRect.top + heightMeasure; super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** * 第二步:把图片的事件交由手势来处理 */ @Override public boolean onTouchEvent(MotionEvent event) { //touchevent事件有手势来处理 mDetector.onTouchEvent(event); return true; } @Override protected void onDraw(Canvas canvas) { Bitmap bm = mDecoder.decodeRegion(mRect, options); //从左上角度开始画 canvas.drawBitmap(bm, 0, 0, null); super.onDraw(canvas); } /** * 向外提供加载图片后得到的输入流 * @param is * @return */ protected void setInputStream(InputStream is){ try { //得到要加载显示的图片区域 mDecoder = BitmapRegionDecoder.newInstance(is, false); BitmapFactory.Options tmpOptions = new BitmapFactory.Options(); tmpOptions.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, tmpOptions); //获得图片的宽高 mImageHeight = tmpOptions.outHeight; mImageWidth = tmpOptions.outWidth; } catch (IOException e) { e.printStackTrace(); } finally{ if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } }}
第四步:实现
public class MainActivity extends Activity { private LargeImageView mImageview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_largeimage); mImageview = (LargeImageView) findViewById(R.id.largeImage); loadImage(); } /** * 从asset文件夹里加载图片 */ private void loadImage() { try { InputStream is = getAssets().open("22.jpg"); mImageview.setInputStream(is); } catch (IOException e) { e.printStackTrace(); } }}
activity_largeimage.xml文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.android.view.largeimageview.LargeImageView android:id="@+id/largeImage" android:layout_width="match_parent" android:layout_height="match_parent" > com.android.view.largeimageview.LargeImageView>RelativeLayout>
—————————————————————————————————————————————————–
JAVA(SSM、SSH等)20项目视频教程,共134G
下载地址:
https://item.taobao.com/item.htm?id=558680925808
———————-课程目录——————————
第01项目:OA办公自动化项目(四套)
第02项目:CRM客户关系管理项目(两套)
第03项目:宅急送项目
第04项目:杰信商贸SSH版
第05项目:电力项目(两套)
第06项目:校内网项目
第07项目:Java邮件开发教程
第08项目:java网上在线支付实战视频
第09项目:俄罗斯方块游戏开发_视频教程
第10项目:交通灯管理系统视频教程
第11项目:银行业务调度系统视频教程
第12项目:供应链系统视频教程
第13项目:网上商城项目
第14项目:药品集中采购系统视频教程
第15项目:杰信商贸SSM版
第16项目:国家税务协同平台项目
第17项目:javaWeb聊天室
第18项目:点餐系统
第19项目:网上书店
第20项目:手机进销存系统
—————————————————————————————————————————————————–
更多相关文章
- Android 图片加载库Glide
- android 自定义图片剪裁
- Android——ImageButton【图片按钮】的点击事件与属性
- 关于LinearLayout布局中,子控件平分宽度
- android 选择本地图片并预览
- linux下eclipse构建并编译android一个简单jni项目
- Android 实现文件(图片)上传
- Android对话框图片全屏