zoukankan      html  css  js  c++  java
  • 类似美图秀秀拼图的原理

    extend:https://github.com/songzhiyong/pathview


    package
    com.example.picpin; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; import android.view.Window; import android.view.WindowManager; public class ShowPathActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(new PathView(this)); } } class PathView extends View { private Context mCtx; private Path[] mPath; private Bitmap[] mBmp; private Matrix[] matrixs; private boolean[] mBmpFlag; private float[][] mPathLT; private float[][] mPathOffset; int mPathNum = 3; private int border = 6; private int viewWdh, viewHgt, itemHgt; public static int PICIDS[] = { R.drawable.catarina, R.drawable.lake, R.drawable.m74hubble, R.drawable.sunset, R.drawable.tahiti }; public PathView(Context context) { super(context); mCtx = context; scaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener()); initialView(); initPath(); } private void initPath() { // mPathNum = (int) (Math.random() * 10); mPath = new Path[mPathNum]; for (int i = 0; i < mPathNum; i++) { mPath[i] = new Path(); } mBmpFlag = new boolean[mPathNum]; mPathLT = new float[mPathNum][2]; mPathOffset = new float[mPathNum][2]; for (int i = 0; i < mPathNum; i++) { mBmpFlag[i] = false; mPathLT[i][0] = 0f; mPathLT[i][1] = 0f; mPathOffset[i][0] = 0f; mPathOffset[i][1] = 0f; } for (int i = 0; i < mPathNum; i++) { mPathLT[i][0] = 0; mPathLT[i][1] = (itemHgt + border) * i; mPath[i].moveTo(mPathLT[i][0], mPathLT[i][1]); mPath[i].lineTo(viewWdh, mPathLT[i][1]); mPath[i].lineTo(viewWdh, mPathLT[i][1] + itemHgt); mPath[i].lineTo(0, mPathLT[i][1] + itemHgt); mPath[i].close(); } // get bitmap mBmp = new Bitmap[mPathNum]; for (int i = 0; i < mPathNum; i++) { BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), PICIDS[i], opt); int bmpWdh = opt.outWidth; int bmpHgt = opt.outHeight; int size = caculateSampleSize(bmpWdh, bmpHgt, viewWdh, itemHgt); opt.inJustDecodeBounds = false; opt.inSampleSize = size; mBmp[i] = BitmapFactory.decodeResource(getResources(), PICIDS[i], opt); } } private int caculateSampleSize(int picWdh, int picHgt, int showWdh, int showHgt) { // 如果此时显示区域比图片大,直接返回 if ((showWdh < picWdh) || (showHgt < picHgt)) { int wdhSample = picWdh / showWdh; int hgtSample = picHgt / showHgt; // 利用小的来处理 int sample = wdhSample > hgtSample ? hgtSample : wdhSample; int minSample = 2; while (sample > minSample) { minSample *= 2; } return minSample >> 1; } else { return 1; } } private void initialView() { DisplayMetrics display = mCtx.getResources().getDisplayMetrics(); viewWdh = display.widthPixels; itemHgt = display.heightPixels >> 2; viewHgt = itemHgt * 3 + 2 * border; Log.d("screen parameter", "wdh = " + viewWdh + ":hgt = " + display.heightPixels); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(viewWdh, viewHgt); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.GRAY);// 显示背景颜色 Paint paint = new Paint(); paint.setColor(Color.GRAY); canvas.drawPaint(paint); // draw1(canvas); draw2(canvas, paint); } private void draw1(Canvas canvas) { for (int i = 0; i < mPathNum; i++) { canvas.save(); canvas.clipPath(mPath[i]); BitmapDrawable mDrawable = new BitmapDrawable(mBmp[i]); float minX = mPathLT[i][0] + mPathOffsetX + mPathOffset[i][0]; float minY = mPathLT[i][1] + mPathOffsetY + mPathOffset[i][1]; mDrawable.setBounds((int) minX, (int) minY, viewWdh, (itemHgt + border) * i + itemHgt); mDrawable.draw(canvas); canvas.restore(); } } private void draw2(Canvas canvas, Paint paint) { for (int i = 0; i < mPathNum; i++) { canvas.save(); // canvas.scale(scaleFactor, scaleFactor); drawScene(canvas, paint, i); canvas.restore(); } } private void drawScene(Canvas canvas, Paint paint, int idx) { canvas.clipPath(mPath[idx]); canvas.drawColor(Color.GRAY); if (mBmpFlag[idx]) { canvas.drawBitmap(mBmp[idx], mPathLT[idx][0] + mPathOffsetX + mPathOffset[idx][0], mPathLT[idx][1] + mPathOffsetY + mPathOffset[idx][1], paint); } else { canvas.drawBitmap(mBmp[idx], mPathLT[idx][0] + mPathOffset[idx][0], mPathLT[idx][1] + mPathOffset[idx][1], paint); } } float ptx, pty; float mPathOffsetX, mPathOffsetY; private float scaleFactor = 1.0f; private ScaleGestureDetector scaleGestureDetector; private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 5.0f)); invalidate(); return true; } } @Override public boolean onTouchEvent(MotionEvent event) { scaleGestureDetector.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: for (int i = 0; i < mPathNum; i++) { mBmpFlag[i] = false; } ptx = event.getRawX(); pty = event.getRawY(); mPathOffsetX = 0; mPathOffsetY = 0; int cflag = 0; for (cflag = 0; cflag < mPathNum; cflag++) { if (contains(mPath[cflag], ptx, pty)) { mBmpFlag[cflag] = true; break; } } break; case MotionEvent.ACTION_MOVE: mPathOffsetX = event.getRawX() - ptx; mPathOffsetY = event.getRawY() - pty; invalidate(); break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_UP: for (int i = 0; i < mPathNum; i++) { if (mBmpFlag[i]) { mPathOffset[i][0] += event.getRawX() - ptx; mPathOffset[i][1] += event.getRawY() - pty; if (mPathOffset[i][0] > 0) { mPathOffset[i][0] = 0; } if (mPathOffset[i][0] < -(mBmp[i].getWidth() - viewWdh)) { mPathOffset[i][0] = -(mBmp[i].getWidth() - viewWdh); } if (mPathOffset[i][1] > 0) { mPathOffset[i][1] = 0; } if (mPathOffset[i][1] < -(mBmp[i].getHeight() - itemHgt)) { mPathOffset[i][1] = -(mBmp[i].getHeight() - itemHgt); } mBmpFlag[i] = false; break; } } invalidate(); break; default: break; } return true; } private boolean contains(Path paramPath, float pointx, float pointy) { RectF localRectF = new RectF(); paramPath.computeBounds(localRectF, true); Region localRegion = new Region(); localRegion.setPath(paramPath, new Region((int) localRectF.left, (int) localRectF.top, (int) localRectF.right, (int) localRectF.bottom)); return localRegion.contains((int) pointx, (int) pointy); } }
  • 相关阅读:
    Android高性能ORM数据库DBFlow入门
    PHP数据库操作
    Smarty模板技术学习(二)
    Smarty模板技术学习
    微信开发简单实例
    支持IE6只是其一!Web开发的十大噩梦
    前端构建工具发展及其比较
    React通过redux-persist持久化数据存储
    vue中Axios的封装和API接口的管理
    yarn使用教程
  • 原文地址:https://www.cnblogs.com/niray/p/4531134.html
Copyright © 2011-2022 走看看