先看效果图
我的思路是,首先我给确定下来我点击的是哪一条边,这个可以用onTouchEvent来监听实现。然后,由于用户很难精确的点击到边上,所有点击时需要存在一定的误差范围。最后,我需要判断每条边的边界情况,例如右边框不能移动到左边框的左边,上边框不能移动到下边框的下面等。
下面是自定义View的源码:
public class MyRectView extends View {
private Paint paint;
private Rect rect;
private int left=200,right=700,top=200,bottom=500;
private int strokeWidth=10;
private boolean onVerticalLeftStroke=false,onVerticalRightStroke=false; //是否在左边框上;右边框上
private boolean onHorizontalUpStroke=false,onHorizontalDownStroke=false;//是否在上边框上;下边框上
private float currentX=0,currentY=0;
public MyRectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
paint=new Paint();
paint.setStrokeWidth(strokeWidth);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
rect=new Rect(left,top,right,bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(rect,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x=event.getX();
float y=event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
currentX=x;currentY=y;
onHorizontalRectStroke(x,y);
onVerticalRectStroke(x,y);
break;
case MotionEvent.ACTION_MOVE:
currentX=x;currentY=y;
moveRectStroke();
break;
case MotionEvent.ACTION_UP:
onHorizontalUpStroke=false;
onHorizontalDownStroke=false;
onVerticalLeftStroke=false;
onVerticalRightStroke=false;
break;
}
return true;
}
//通过边框移动矩形(重画)
private void moveRectStroke(){
if(onVerticalLeftStroke){
left=(int)currentX;
//检查左边框的边界
if(left<0)left=0;
if(left>right-25)left=right-25;
redrawRect();
}else if(onVerticalRightStroke){
right=(int)currentX;
//检查右边框的边界
if(right>Constants.SCREEN_WIDTH)right=900;
if(right<left+25)right=left+25;
redrawRect();
}else if(onHorizontalUpStroke){
top=(int)currentY;
//检查上边框的边界
if(top<0)top=0;
if(top>bottom-25)top=bottom-25;
redrawRect();
}else if(onHorizontalDownStroke){
bottom=(int)currentY;
//检查下边框的边界
if(bottom>Constants.SCREEN_HEIGHT)bottom=1500;
if(bottom<top+25)bottom=top+25;
redrawRect();
}
}
//重绘矩形
private void redrawRect(){
rect.set(left,top,right,bottom);
invalidate();
}
//是否在矩形边框上
private void onVerticalRectStroke(float x,float y){
//在竖边框上
if(y>=top && y<=bottom){
//在左边框上(在一定的误差范围内)
if(x<=left+strokeWidth*5 && x>=left-strokeWidth*5){
onVerticalLeftStroke=true;
}
//在右边框上(在一定的误差范围内)
else if(x<=right+strokeWidth*5 && x>=right-strokeWidth*5){
onVerticalRightStroke=true;
}
}
}
//是否在矩形边框上
private void onHorizontalRectStroke(float x,float y){
//在横边框上
if(x>=left && x<=right){
//在上边框上(在一定的误差范围内)
if(y<=top+strokeWidth*5 && y>=top-strokeWidth*5){
onHorizontalUpStroke=true;
}
//在下边框上(在一定的误差范围内)
else if(y<=bottom+strokeWidth*5 && y>=bottom-strokeWidth*5) {
onHorizontalDownStroke=true;
}
}
}
}
Activity类:
public class MyRectAct extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_rect);
}
}
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.hualinfo.myviewtext.MyRectView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>