Android 不规则多边形ImageView布局问题,大神在哪里?

梅明子 2014-12-17 09:18:12

就是上图中红圈部分的布局,分别有三个可编辑的ImageView,也就是说单击可以添加图片,其中还可以多点触控,实现缩放和移动,但撇开触控不说,就布局都很蛋痛了,求大神支招!求demo,求案例!
...全文
983 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
丿末兮 2016-12-16
  • 打赏
  • 举报
回复
楼主有dome共享一下吗 我想学习一下
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复

import java.io.IOException;

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.Path;
import android.util.AttributeSet;
import android.view.View;

public class ImageClipView extends View {

	private Bitmap leftImage;
	private Bitmap rightImage;
	private Bitmap downImage;
	private Matrix leftMatrix;
	private Matrix rightMatrix;
	private Matrix downMatrix;
	private float padding = 10;
	private Path left;
	private Path right;
	private Path down;
	private Paint paint;
	
	private int state = -1;
	private final int START = 1;
	
	public ImageClipView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
	}

	public ImageClipView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public ImageClipView(Context context) {
		super(context);
	}

	private void init(){
		try {
			leftImage = BitmapFactory.decodeStream(getContext().getAssets().open("clip_image.png"));
			rightImage = BitmapFactory.decodeStream(getContext().getAssets().open("right.png"));
			downImage = BitmapFactory.decodeStream(getContext().getAssets().open("down.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}

		paint = new Paint();
		paint.setAntiAlias(true);
		initMatrix();
		initPath();
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if(leftImage != null){
			canvas.save();
			canvas.clipPath(left);
			canvas.drawBitmap(leftImage, leftMatrix, paint);
			canvas.restore();
			canvas.save();
			canvas.clipPath(right);
			canvas.drawBitmap(rightImage, rightMatrix, paint);
			canvas.restore();
			canvas.save();
			canvas.clipPath(down);
			canvas.drawBitmap(downImage, downMatrix, paint);
			canvas.restore();
		}
	}
	
	@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 initMatrix(){
		leftMatrix = new Matrix();
		rightMatrix = new Matrix();
		downMatrix = new Matrix();
		
		float w = getWidth();
		float h = getHeight();
		
		//第一个图片
		float scale = 1;
		float scaleX = w / leftImage.getWidth();
		float 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);
		//第三个图片
		scaleX = w / downImage.getWidth();
		scaleY = h / downImage.getHeight();
		scale = scaleX > scaleY ? scaleX : scaleY;
		downMatrix.setScale(scale, scale);
		
	}
	
	private void initPath(){
		
		float cpad = padding / 2;//padding = 10
		
		float w = getWidth();
		float h = getHeight();
		float bx = w / 2;
		float by = h / 2;
		
		left = new Path();
		right = new Path();
		down = new Path();
		
		left.moveTo(padding, padding);
		left.lineTo(bx - cpad, padding);
		left.lineTo(bx - cpad, by);
		left.lineTo(padding, h - 1.7f * padding);
		left.lineTo(padding, padding);
		left.close();
		
		right.moveTo(bx + cpad, padding);
		right.lineTo(w - padding, padding);
		right.lineTo(w - padding, h - 1.7f * padding);
		right.lineTo(bx + cpad, by);
		right.lineTo(bx + cpad, padding);
		right.close();
		
		down.moveTo(bx, by + 0.7f * padding);
		down.lineTo(padding * 1.41f, h - padding);
		down.lineTo(w - padding* 1.41f, h - padding);
		down.lineTo(bx, by + 0.7f * padding);
		down.close();
		
	}
	
}
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复
这个有点麻烦的,费时费力。基本上要用自定义控件,重写onDraw和onTouch,
onDraw主要处理绘制出来的区域。
onTouch主要是处理触控事件。
我这简单的实现了onDraw,没时间弄。
代码一会贴在下面
Alish_Brown 2014-12-17
  • 打赏
  • 举报
回复
引用 4 楼 baidu_23478311 的回复:
引用 2 楼 stand123 的回复:
标准控件不好实现,只能自定义了,或者完全自绘制
请问你会吗?我感觉都天塌下来了,完全不会啊
自绘制的话,是这样: 定义View的一个子类,重写 onDraw(), onTouch()等方法
哎,真难 2014-12-17
  • 打赏
  • 举报
回复
这是不是要做拼图啊,你百度下拼图的案例,其实重点是在写layout,如果把这个不规则的layout写出来,我感觉是自定义了layout才能把这样的不规则图形画出来的
梅明子 2014-12-17
  • 打赏
  • 举报
回复
引用 2 楼 stand123 的回复:
标准控件不好实现,只能自定义了,或者完全自绘制
请问你会吗?我感觉都天塌下来了,完全不会啊
梅明子 2014-12-17
  • 打赏
  • 举报
回复
引用 1 楼 bdmh 的回复:
我宁可自己在onDraw中绘制三个区域
请问怎么绘制呀?我就是不会,自定义控件底子很差
Alish_Brown 2014-12-17
  • 打赏
  • 举报
回复
标准控件不好实现,只能自定义了,或者完全自绘制
bdmh 2014-12-17
  • 打赏
  • 举报
回复
我宁可自己在onDraw中绘制三个区域
梅明子 2014-12-17
  • 打赏
  • 举报
回复
引用 21 楼 lxfhjjsfq 的回复:
里面实现了点击替换图片的功能,也是说说点击的区域判断完成了。至于要缩放什么的就要你自己在onTouch中细化逻辑了,有时间的话就结贴吧。或者再等等有没有更好的方案。
果然是那个东西(setLayerType(View.LAYER_TYPE_SOFTWARE, null);)刚才查了下这个,也好难理解。算了,先不去理解了,你现在给的代码,我还得花时间好好研究下,等会我加上缩放试试看行不行,这次真的是太感谢你的帮助了!对于我来讲,就是起到了一个启蒙的作用。不然还真不知道用什么方式去实现这样的布局。真心感谢!
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复

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.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

@SuppressLint("NewApi") 
public class ImageClipView extends View {

	private Bitmap leftImage;
	private Bitmap rightImage;
	private Bitmap downImage;
	private Matrix leftMatrix;
	private Matrix rightMatrix;
	private Matrix downMatrix;
	private float padding = 10;
	private Path left;
	private Path right;
	private Path down;
	private Paint paint;
	
	private int state = -1;
	private final int START = 1;
	
	public ImageClipView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
	}

	public ImageClipView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public ImageClipView(Context context) {
		super(context);
	}

	private void init(){
		setLayerType(View.LAYER_TYPE_SOFTWARE, null);
		try {
			leftImage = BitmapFactory.decodeStream(getContext().getAssets().open("clip_image.png"));
			rightImage = BitmapFactory.decodeStream(getContext().getAssets().open("right.png"));
			downImage = BitmapFactory.decodeStream(getContext().getAssets().open("down.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}

		paint = new Paint();
		paint.setAntiAlias(true);
		initMatrix();
		initPath();
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if(leftImage != null){
			canvas.save();
			canvas.clipPath(left);
			canvas.drawBitmap(leftImage, leftMatrix, paint);
			canvas.restore();
			canvas.save();
			canvas.clipPath(right);
			canvas.drawBitmap(rightImage, rightMatrix, paint);
			canvas.restore();
			canvas.save();
			canvas.clipPath(down);
			canvas.drawBitmap(downImage, downMatrix, paint);
			canvas.restore();
		}
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		
		switch(event.getAction()){
		case MotionEvent.ACTION_DOWN:
			if(isInsideLeft(event)){
				Bitmap temp = leftImage;
				leftImage = rightImage;
				rightImage = temp;
				
				Matrix tm = leftMatrix;
				leftMatrix = rightMatrix;
				rightMatrix = tm;
			}
			else if(isInsideRight(event)){
				Bitmap temp = rightImage;
				rightImage = downImage;
				downImage = temp;
				
				Matrix tm = rightMatrix;
				rightMatrix = downMatrix;
				downMatrix = tm;
			}else if(isInsideDown(event)){
				Bitmap temp = downImage;
				downImage = leftImage;
				leftImage = temp;
				
				Matrix tm = downMatrix;
				downMatrix = leftMatrix;
				leftMatrix = tm;
			}
			break;
		}
		invalidate();
		return super.onTouchEvent(event);
	}
	
	@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 initMatrix(){
		leftMatrix = new Matrix();
		rightMatrix = new Matrix();
		downMatrix = new Matrix();
		
		float w = getWidth();
		float h = getHeight();
		
		//第一个图片
		float scale = 1;
		float scaleX = w / leftImage.getWidth();
		float 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);
		//第三个图片
		scaleX = w / downImage.getWidth();
		scaleY = h / downImage.getHeight();
		scale = scaleX > scaleY ? scaleX : scaleY;
		downMatrix.setScale(scale, scale);
		
	}
	
	private void initPath(){
		
		float cpad = padding / 2;//padding = 10
		
		float w = getWidth();
		float h = getHeight();
		float bx = w / 2;
		float by = h / 2;
		
		left = new Path();
		right = new Path();
		down = new Path();
		
		left.moveTo(padding, padding);
		left.lineTo(bx - cpad, padding);
		left.lineTo(bx - cpad, by);
		left.lineTo(padding, h - 1.7f * padding);
		left.lineTo(padding, padding);
		left.close();
		
		right.moveTo(bx + cpad, padding);
		right.lineTo(w - padding, padding);
		right.lineTo(w - padding, h - 1.7f * padding);
		right.lineTo(bx + cpad, by);
		right.lineTo(bx + cpad, padding);
		right.close();
		
		down.moveTo(bx, by + 0.7f * padding);
		down.lineTo(padding * 1.41f, h - padding);
		down.lineTo(w - padding* 1.41f, h - padding);
		down.lineTo(bx, by + 0.7f * padding);
		down.close();
		
	}
	
	private boolean isInsideLeft(MotionEvent event){
		float x = event.getX();
		float y = event.getY();
		float w = getWidth();
		float h = getHeight();
		float bx = w / 2;
		float by = h / 2;
		
		if(x < 0 || x > bx || y < 0 || y > h){
			return false;
		}
		if(x + y - w < 0){
			return true;
		}
		return false;
	}
	
	private boolean isInsideRight(MotionEvent event){
		float x = event.getX();
		float y = event.getY();
		float w = getWidth();
		float h = getHeight();
		float bx = w / 2;
		float by = h / 2;
		
		if(x < bx || x > w || y < 0 || y > h){
			return false;
		}
		if(x > y){
			return true;
		}
		return false;
	}
	
	private boolean isInsideDown(MotionEvent event){
		float x = event.getX();
		float y = event.getY();
		float w = getWidth();
		float h = getHeight();
		float bx = w / 2;
		float by = h / 2;
		
		if(y < by || y > h){
			return false;
		}
		if(x < y && x + y - w > 0){
			return true;
		}
		return false;
	}
}
里面实现了点击替换图片的功能,也是说说点击的区域判断完成了。至于要缩放什么的就要你自己在onTouch中细化逻辑了,有时间的话就结贴吧。或者再等等有没有更好的方案。
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复
好吧,我知道是什么问题了,开启一下软件加速。
梅明子 2014-12-17
  • 打赏
  • 举报
回复
引用 18 楼 lxfhjjsfq 的回复:
华为三星应该都没问题,不太可能出现哪个机型不支持的问题,毕竟是比较早的api了
恩,但是问题就是这样了,搞不懂,你能方便把你demo发给我吗?邮箱:qiulong_888@163.com
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复
华为三星应该都没问题,不太可能出现哪个机型不支持的问题,毕竟是比较早的api了
梅明子 2014-12-17
  • 打赏
  • 举报
回复
引用 16 楼 lxfhjjsfq 的回复:
我测试了2个三星手机都没问题
不会吧!我这边测试了三个4.2的三星,一个4.3的都不行,然后测试了一个4.4的小米就OK了。这是为什么呀?代码都和你一样的,想不通...
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复
我测试了2个三星手机都没问题
梅明子 2014-12-17
  • 打赏
  • 举报
回复
引用 14 楼 lxfhjjsfq 的回复:
你仔细看看你的代码,我测试的都没有问题
代码是和你的一样的,我就是直接拿下来先试试看,结果发现小米就是OK的,三星就成那样了。
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复
你仔细看看你的代码,我测试的都没有问题
梅明子 2014-12-17
  • 打赏
  • 举报
回复
引用 7 楼 lxfhjjsfq 的回复:
这个有点麻烦的,费时费力。基本上要用自定义控件,重写onDraw和onTouch,
onDraw主要处理绘制出来的区域。
onTouch主要是处理触控事件。
我这简单的实现了onDraw,没时间弄。

你好,那个错,是我的图片放在res文件夹下面,是我的失误,不好意思啦!^_^ 但是我发现,你这个只支持小米哦,在别的手机就不行了。
_xianfeng99 2014-12-17
  • 打赏
  • 举报
回复
leftImage = BitmapFactory.decodeStream(getContext().getAssets().open("clip_image.png"));
            rightImage = BitmapFactory.decodeStream(getContext().getAssets().open("right.png"));
            downImage = BitmapFactory.decodeStream(getContext().getAssets().open("down.png"));
替换成你的图片
加载更多回复(3)

80,349

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧