当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义View实现可拖拽缩放的矩形框

Android自定义View实现可拖拽缩放的矩形框

2020年06月18日  | 移动技术网IT编程  | 我要评论

最后一次说我爱你,帮美女挤奶,青岛沙画培训

本文实例为大家分享了android自定义view拖拽缩放矩形框的具体代码,供大家参考,具体内容如下

在开发项目中,需要一个矩形框来实现截屏功能,并且还需要可以任意拖拽和缩放,这就需要自定义view来实现了,具体功能如下:

1.自定义view

package com.xinrui.screenshot.view;

import android.content.context;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.rectf;
import android.support.annotation.nullable;
import android.util.attributeset;
import android.util.log;
import android.util.typedvalue;
import android.view.motionevent;
import android.view.view;

public class croprectview extends view {
 
 // 绘制 损害框和损害名称
 private paint mpaint;
 private rectf mrectf;
 
 // 边缘字体
// private borderedtext mborderedtext;
 
 // 标题 或 名字
 private string mtitle;
 // 概率
 private float mconfidence;
 
 // 矩形框 corner 的角度:直角、圆角
 private int mcornerangle;
 
 //直角 默认
 public static final int right_corner = 0;
 //圆角
 public static final int round_corner = 1;
 
 // remove rect
 private int mode;
 private static final int mode_outside = 0x000000aa;/*170*/
 private static final int mode_inside = 0x000000bb;/*187*/
 private static final int mode_point = 0x000000cc;/*204*/
 private static final int mode_illegal = 0x000000dd;/*221*/
 
 private float startx;/*start x location*/
 private float starty;/*start y location*/
 private float endx;/*end x location*/
 private float endy;/*end y location*/
 
 private float currentx;/*x coordinate values while finger press*/
 private float currenty;/*y coordinate values while finger press*/
 
 private float memoryx;/*the last time the coordinate values of x*/
 private float memoryy;/*the last time the coordinate values of y*/
 
 private float mcoverwidth;/*width of selection box*/
 private float mcoverheight;/*height of selection box*/
 
 private static final int accuracy = 100;/*touch accuracy*/
 private int pointposition;/*vertex of a rectangle*/
 
 private static final float minwidth = 100.0f;/*the minimum width of the rectangle*/
 private static final float minheight = 200.0f;/*the minimum height of the rectangle*/
 
 private onlocationlistener mlocationlistener;/*listen to the rect */
 
 private static final float edge_width = 1.8f;
 
 public moveandcroprectview(context context) {
  this(context, null);
 }
 
 public moveandcroprectview(context context, @nullable attributeset attrs) {
  this(context, attrs, 0);
 }
 
 public moveandcroprectview(context context, @nullable attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  initdatas(context);
 }
 
 private void initdatas(context context) {
  mpaint = new paint();
  mrectf = new rectf();
 
  //画笔设置空心
  mpaint.setstyle(paint.style.stroke);
  mpaint.setcolor(color.white);
  mpaint.setstrokewidth(2);
  mpaint.setantialias(true);
 
//  float textsizepx = typedvalue.applydimension(typedvalue.complex_unit_dip,
//    18.0f, context.getresources().getdisplaymetrics());
//  mborderedtext = new borderedtext(textsizepx);
  currentx = 0;
  currenty = 0;
 }
 
 private boolean firstdraw = true;
 
 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
 
//  switch (mcornerangle) {
//   case right_corner:// 绘制 损害框(直角矩形框)
//    drawrect(canvas);
//    break;
//   case round_corner:// 绘制 损害框(圆角矩形框)
//    drawroundrect(canvas);
//    break;
//  }
 
  if (firstdraw) {
   firstdraw = false;
   startx = mrectf.left;
   starty = mrectf.top;
   endx = mrectf.right;
   endy = mrectf.bottom;
 
   mcoverwidth = mrectf.width();
   mcoverheight = mrectf.height();
  }
 
 
  if (mlocationlistener != null) {
   mlocationlistener.locationrect(startx, starty, endx, endy);
  }
 
//  logutils.d("ondraw -- startx: " + startx);
 
  canvas.drawline(startx - edge_width, starty - edge_width,
    endx + edge_width, starty - edge_width, mpaint);/*top 上边框-*/
  canvas.drawline(startx - edge_width, endy + edge_width,
    endx + edge_width, endy + edge_width, mpaint);/*bottom -*/
  canvas.drawline(startx - edge_width, starty - edge_width,
    startx - edge_width, endy + edge_width, mpaint);/*left |*/
  canvas.drawline(endx + edge_width, starty - edge_width,
    endx + edge_width, endy + edge_width, mpaint);/*right |*/
 
  // 绘制名称 和 概率
//  final string labelstring =
//    !textutils.isempty(mtitle)
//      ? string.format("%s %.2f", mtitle, (100 * mconfidence))
//      : string.format("%.2f", (100 * mconfidence));
//
//  // 在 直角矩形框 上写字
//  mborderedtext.drawtext(canvas,
//    startx,
//    starty, labelstring + "%",
//    mpaint);
 }
 
 @suppresswarnings("nullableproblems")
 @override
 public boolean ontouchevent(motionevent event) {
  switch (event.getaction()) {
   case motionevent.action_down:
    memoryx = event.getx();
    memoryy = event.gety();
    checkmode(memoryx, memoryy);
    break;
   case motionevent.action_move: {
    currentx = event.getx();
    currenty = event.gety();
    switch (mode) {
     case mode_illegal:
      recoverfromillegal(currentx, currenty);
      postinvalidate();
      break;
     case mode_outside:
      //do nothing;
      break;
     case mode_inside://拖动
      movebytouch(currentx, currenty);
      postinvalidate();
      break;
     default:
      /*mode_point*/
      movebypoint(currentx, currenty);
      postinvalidate();
      break;
    }
   }
   break;
   case motionevent.action_up:
//    mpaint.setcolor(getcontext().getresources().getcolor(r.color.orange));
    postinvalidate();
    break;
   default:
    break;
  }
  return true;
 }
 
 /*点击顶点附近时的缩放处理*/
 @suppresswarnings("suspiciousnamecombination")
 private void movebypoint(float bx, float by) {
//  logutils.d("movebypoint");
  switch (pointposition) {
   case 0:/*left-up*/
    mcoverwidth = math.abs(endx - bx);
    mcoverheight = math.abs(endy - by);
    //noinspection suspiciousnamecombination
    if (!checklegalrect(mcoverwidth, mcoverheight)) {
     mode = mode_illegal;
    } else {
     refreshlocation(bx, by, endx, endy);
    }
    break;
   case 1:/*right-up*/
    mcoverwidth = math.abs(bx - startx);
    mcoverheight = math.abs(endy - by);
    if (!checklegalrect(mcoverwidth, mcoverheight)) {
     mode = mode_illegal;
    } else {
     refreshlocation(startx, by, bx, endy);
    }
    break;
   case 2:/*left-down*/
    mcoverwidth = math.abs(endx - bx);
    mcoverheight = math.abs(by - starty);
    if (!checklegalrect(mcoverwidth, mcoverheight)) {
     mode = mode_illegal;
    } else {
     refreshlocation(bx, starty, endx, by);
    }
    break;
   case 3:/*right-down*/
    mcoverwidth = math.abs(bx - startx);
    mcoverheight = math.abs(by - starty);
    if (!checklegalrect(mcoverwidth, mcoverheight)) {
     mode = mode_illegal;
    } else {
     refreshlocation(startx, starty, bx, by);
    }
    break;
   default:
    break;
  }
 }
 
 /*刷新矩形的坐标*/
 private void refreshlocation(float isx, float isy, float iex, float iey) {
  this.startx = isx;
  this.starty = isy;
  this.endx = iex;
  this.endy = iey;
 
  mcoverwidth = endx - startx;
  mcoverheight = endy - starty;

 }
 
 /*检测矩形是否达到最小值*/
 private boolean checklegalrect(float cheight, float cwidth) {
  return (cheight > minheight && cwidth > minwidth);
 }
 
 /*从非法状态恢复,这里处理的是达到最小值后能拉伸放大*/
 private void recoverfromillegal(float rx, float ry) {
  if ((rx > startx && ry > starty) && (rx < endx && ry < endy)) {
   mode = mode_illegal;
  } else {
   mode = mode_point;
  }
 }

 /**
  * 判断点在矩形的什么位置
  * @param cx
  * @param cy
  */
 private void checkmode(float cx, float cy) {
  if (cx > startx && cx < endx && cy > starty && cy < endy) {
   mode = mode_inside;//矩形内部
  } else if (nearbypoint(cx, cy) < 4) {
   mode = mode_point;//矩形点上
  } else {
   mode = mode_outside;//矩形外部
  }
 }
 
 /*矩形随手指移动*/
 private void movebytouch(float mx, float my) {/*move center point*/
  float dx = mx - memoryx;
  float dy = my - memoryy;

  startx += dx;
  starty += dy;
  if(startx<=0){
   startx=0;
  }
  if(starty<=0){
   starty=0;
  }
  endx = startx + mcoverwidth;
  endy = starty + mcoverheight;
  if(endx>=1920){
   endx=1920;
   startx=endx-mcoverwidth;
  }
  if(endy>=1080){
   endy=1080;
   starty=endy-mcoverheight;
  }
  memoryx = mx;
  memoryy = my;
 }
 
 /*判断点(inx,iny)是否靠近矩形的4个顶点*/
 private int nearbypoint(float floatx, float floaty) {
  if ((math.abs(startx - floatx) <= accuracy && (math.abs(floaty - starty) <= accuracy))) {/*left-up angle*/
   pointposition = 0;
   return 0;
  }
  if ((math.abs(endx - floatx) <= accuracy && (math.abs(floaty - starty) <= accuracy))) {/*right-up angle*/
   pointposition = 1;
   return 1;
  }
  if ((math.abs(startx - floatx) <= accuracy && (math.abs(floaty - endy) <= accuracy))) {/*left-down angle*/
   pointposition = 2;
   return 2;
  }
  if ((math.abs(endx - floatx) <= accuracy && (math.abs(floaty - endy) <= accuracy))) {/*right-down angle*/
   pointposition = 3;
   return 3;
  }
  pointposition = 100;
  return 100;
 }
 
 // 设置矩形框
 public void setrectf(rectf rectf) {
  this.mrectf = rectf;
 }
 
 public void settitle(string title) {
  mtitle = title;
 }
 
 public void setconfidence(float confidence) {
  mconfidence = confidence;
 }
 
 public void setcornerangle(int cornerangle) {
  this.mcornerangle = cornerangle;
 }
 
 // 绘制 损害框(直角矩形框)
 private void drawrect(canvas canvas) {
 
  canvas.drawrect(mrectf, mpaint);
 
  // 绘制名称 和 概率
//  final string labelstring =
//    !textutils.isempty(mtitle)
//      ? string.format("%s %.2f", mtitle, (100 * mconfidence))
//      : string.format("%.2f", (100 * mconfidence));
 
  // 在 直角矩形框 上写字
//  mborderedtext.drawtext(canvas,
//    mrectf.left,
//    mrectf.top, labelstring + "%",
//    mpaint);
 }
 
 // 绘制 损害框(圆角矩形框)
 private void drawroundrect(canvas canvas) {
  float cornersize = math.min(mrectf.width(), mrectf.height()) / 8.0f;
  canvas.drawroundrect(mrectf, cornersize, cornersize, mpaint);
 
  // 绘制名称 和 概率
//  final string labelstring =
//    !textutils.isempty(mtitle)
//      ? string.format("%s %.2f", mtitle, (100 * mconfidence))
//      : string.format("%.2f", (100 * mconfidence));
 
  // 在 圆角矩形框 上写字
//  mborderedtext.drawtext(canvas,
//    mrectf.left + cornersize,
//    mrectf.top, labelstring + "%",
//    mpaint);
 }
 
 public void setlocationlistener(onlocationlistener mlocationlistener) {
  this.mlocationlistener = mlocationlistener;
 }
 
 public interface onlocationlistener {
  void locationrect(float startx, float starty, float endx, float endy);
 }
 
 
}

2.activity里的应用

package com.xinrui.screenshot;

import android.app.activity;
import android.graphics.rectf;
import android.os.bundle;
import android.util.log;
import android.widget.relativelayout;

import com.xinrui.screenshot.view.croprectview;

public class mainactivity extends activity {
 private relativelayout main_area;
 croprectview croprectview;
 @override
 protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);
  initview();
 }

 private void initview(){
  main_area = (relativelayout)findviewbyid(r.id.main_area);
  croprectview = (croprectview)findviewbyid(r.id.main_img);
  rectf rectf = new rectf(660, 240, 1260, 840);
  croprectview.setrectf(rectf);

  croprectview.setlocationlistener(new croprectview.onlocationlistener() {
   @override
   public void locationrect(float startx, float starty, float endx, float endy) {
    log.e("mainactivity","[ startx:(" + startx + ")--starty:(" + starty + ")--endx:(" + endx + ")--endy:(" + endy + ") ]");
   }
  });
 }
}

3.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<relativelayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/main_area"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <com.xinrui.screenshot.view.croprectview
  android:id="@+id/main_img"
  android:layout_centerinparent="true"
  android:layout_width="match_parent"
  android:layout_height="match_parent"/>
</relativelayout>

大功告成。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网