android 不规则标签,Android开发不规则ImageView布局

不啰嗦,直接上代码!注释已经在代码里写的比较详细了!不懂的地方欢迎提问。

import java.io.IOException;

import android.annotation.SuppressLint;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.PaintFlagsDrawFilter;

import android.graphics.Path;

import android.graphics.PointF;

import android.util.AttributeSet;

import android.util.FloatMath;

import android.util.Log;

import android.view.MotionEvent;

import android.view.View;

//自定义类继承View

@SuppressLint({"NewApi", "DrawAllocation" })

public class CustomFourImageView extends View {

//用于判断只在第一次绘制才初始化一些资源数据

private int state = -1;

private final int START = 1;

private Bitmap topImage;

private Bitmap bottomImage;

private Bitmap leftImage;

private Bitmap rightImage;

private Paint paint;

private Matrix topMatrix;

private Matrix bottomMatrix;

private Matrix leftMatrix;

private Matrix rightMatrix;

private float padding = 14;//边框的大小(实则为10px)

private Path top;

private Path bottom;

private Path left;

private Path right;

/** 记录是拖拉照片模式还是放大缩小照片模式 */

private int mode = 0;// 初始状态

/** 拖拉照片模式 */

private static final int MODE_DRAG = 1;

/** 放大缩小照片模式 */

private static final int MODE_ZOOM = 2;

/** 用于记录开始时候的坐标位置 */

private PointF startPoint = new PointF();

/** 两个手指的开始距离 */

private float startDis;

/** 两个手指的中间点 */

private PointF midPoint;

private static int TYPE = 0;

public CustomFourImageView(Context context, AttributeSet attrs,int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

public CustomFourImageView(Context context, AttributeSet attrs) {

super(context, attrs);

}

public CustomFourImageView(Context context) {

super(context);

}

@Override

protected void onLayout(boolean changed, int left, int top, int right,int bottom) {

super.onLayout(changed, left, top, right, bottom);

if (state > 0) {

return;

}

state = START;

init();

}

//初始化

private void init() {

setLayerType(View.LAYER_TYPE_SOFTWARE, null);// 软件加速

try {

topImage = BitmapFactory.decodeStream(getContext().getAssets().open("m1.jpg"));

bottomImage = BitmapFactory.decodeStream(getContext().getAssets().open("m2.jpg"));

leftImage = BitmapFactory.decodeStream(getContext().getAssets().open("m3.jpg"));

rightImage = BitmapFactory.decodeStream(getContext().getAssets().open("m4.jpg"));

} catch (IOException e) {

e.printStackTrace();

}

paint = new Paint();

paint.setAntiAlias(true);

paint.setDither(true);// 防抖动

paint.setFilterBitmap(true);// 过滤

initMatrix();// 缩小图片

initPath();

}

// 初始化矩阵(3X3)并缩放图片为原图的2分之1

private void initMatrix() {

topMatrix = new Matrix();

bottomMatrix = new Matrix();

leftMatrix = new Matrix();

rightMatrix = new Matrix();

float w = getWidth();

float h = getWidth();

// 第一个图片

float scale = 1;// 缩放量

float scaleX = w / topImage.getWidth();

float scaleY = h / topImage.getHeight();

scale = scaleX > scaleY ? scaleX : scaleY;

topMatrix.setScale(scale, scale);// 开始缩放比例

// 第二个图片

scaleX = w / bottomImage.getWidth();

scaleY = h / bottomImage.getHeight();

scale = scaleX > scaleY ? scaleX : scaleY;

bottomMatrix.setScale(scale, scale);

// 第三个图片

scaleX = w / leftImage.getWidth();

scaleY = h / leftImage.getHeight();

scale = scaleX > scaleY ? scaleX : scaleY;

leftMatrix.setScale(scale, scale);

// 第四个图片

scaleX = w / rightImage.getWidth();

scaleY = h / rightImage.getHeight();

scale = scaleX > scaleY ? scaleX : scaleY;

rightMatrix.setScale(scale, scale);

}

// 画好矩阵模块

private void initPath() {

float cpad = padding / 2;// padding = 10

// 视图宽高

float w = getWidth();

float h = getWidth();

float bx = w / 2;//

float by = h / 2;// 相当于中心点

float bxx = bx / 2;//

float byy = by / 2;

top = new Path();

bottom = new Path();

left = new Path();

right = new Path();

// 上图

top.moveTo(padding, padding);

top.lineTo(w -bxx-cpad, padding);

top.lineTo(bx - cpad, by - cpad);

top.lineTo(padding, byy - cpad);

top.close();

// 左图

left.moveTo(padding, byy + cpad);

left.lineTo(bx - cpad, by+cpad);

left.lineTo(bxx - cpad, h - padding);

left.lineTo(padding, h - padding);

left.close();

// 下图

bottom.moveTo(bxx+cpad, h-padding);

bottom.lineTo(w -padding, h-padding);

bottom.lineTo(w - padding, h - byy+cpad);

bottom.lineTo(bx+cpad, by+cpad);

bottom.close();

// 右图

right.moveTo(w - bxx+cpad, padding);

right.lineTo(w -padding, padding);

right.lineTo(w - padding, h - byy-cpad);

right.lineTo(bx+cpad, by-cpad);

right.close();

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if (topImage != null) {

// 设置抗锯齿

PaintFlagsDrawFilter pfd = new PaintFlagsDrawFilter(0,Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

canvas.setDrawFilter(pfd);

canvas.save();

canvas.clipPath(top);// 先画好模块

canvas.drawBitmap(topImage, topMatrix, paint);// 再画图

canvas.restore();

canvas.save();

canvas.clipPath(left);

canvas.drawBitmap(leftImage, leftMatrix, paint);

canvas.restore();

canvas.save();

canvas.clipPath(bottom);

canvas.drawBitmap(bottomImage, bottomMatrix, paint);

canvas.restore();

canvas.save();

canvas.clipPath(right);

canvas.drawBitmap(rightImage, rightMatrix, paint);

canvas.restore();

}

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction() & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN:

// 当第一个手指按下时

mode = MODE_DRAG;

if (isInsideTop(event)) {

// 上图

TYPE = 1;

startPoint.set(event.getX(), event.getY());

} else if (isInsideBottom(event)) {

// 下图

TYPE = 2;

startPoint.set(event.getX(), event.getY());

} else if (isInsideLeft(event)) {

// 左图

TYPE = 3;

startPoint.set(event.getX(), event.getY());

}else if(isInsideRight(event)){

// 右图

TYPE = 4;

startPoint.set(event.getX(), event.getY());

}

break;

case MotionEvent.ACTION_MOVE:

// 移动或缩放

if (mode == MODE_DRAG) {// 拖拉图片

float dx = event.getX() - startPoint.x;// 减去第一次的移动距离

float dy = event.getY() - startPoint.y;

startPoint.x = event.getX();

startPoint.y = event.getY();

// 在没有移动之前的位置上进行移动

getCurrentMatrix().postTranslate(dx, dy);

} else if (mode == MODE_ZOOM) {// 放大缩小图片

float endDis = distance(event);

// 结束距离

if (endDis > 10f) {

// 两个手指并拢在一起的时候素大于10

float scale = endDis / startDis;

startDis = endDis;

// 得到缩放倍数进行缩放

getCurrentMatrix().postScale(scale, scale, midPoint.x,midPoint.y);

}

}

break;

case MotionEvent.ACTION_UP:

// 当触点离开屏幕,但是屏幕上还有触点(手指)

break;

case MotionEvent.ACTION_POINTER_UP:

mode = 0;

break;

case MotionEvent.ACTION_POINTER_DOWN:

// 当屏幕上已经有触点(手指),再有一个触点压下屏幕

mode = MODE_ZOOM;

startDis = distance(event);

if (startDis > 10f) { // 两个手指并拢在一起的时候像素大于10

midPoint = mid(event);

// 记录当前ImageView的缩放倍数

}

break;

}

invalidate();// 重绘

return true;

}

private Matrix getCurrentMatrix() {

switch (TYPE) {

case 1:

return topMatrix;

case 2:

return bottomMatrix;

case 3:

return leftMatrix;

default:

return rightMatrix;

}

}

//计算上图的焦点范围

private boolean isInsideTop(MotionEvent event) {

float x = event.getX();

float y = event.getY();

float w = getWidth();

return y < (-2*x + 3*w/2) && y < (x/2 + w/4);

}

//计算下图的焦点范围

private boolean isInsideBottom(MotionEvent event) {

float x = event.getX();

float y = event.getY();

float w = getWidth();

return y > (-2*x + 3*w/2) && y > (x/2 + w/4);

}

//计算左图的焦点范围

private boolean isInsideLeft(MotionEvent event) {

float x = event.getX();

float y = event.getY();

float w = getWidth();

return y < (-2*x + 3*w/2) && y > (x/2 + w/4);

}

//计算右图的焦点范围

private boolean isInsideRight(MotionEvent event) {

float x = event.getX();

float y = event.getY();

float w = getWidth();

return y > (-2*x + 3*w/2) && y < (x/2 + w/4);

}

/** 计算两个手指间的距离 */

private float distance(MotionEvent event) {

float dx = event.getX(1) - event.getX(0);

float dy = event.getY(1) - event.getY(0);

/** 使用勾股定理返回两点之间的距离 */

return FloatMath.sqrt(dx * dx + dy * dy);

}

/** 计算两个手指间的中间点 */

private PointF mid(MotionEvent event) {

float midX = (event.getX(1) + event.getX(0)) / 2;

float midY = (event.getY(1) + event.getY(0)) / 2;

return new PointF(midX, midY);

}

}

运行之后的效果图:

0818b9ca8b590ca3270a3433284dd417.png

仅供参考!如有不好的地方欢迎提供建议和讨论!(注:转载请注明出处!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值