Android实现控件的缩放移动功能

上篇文章给大家介绍了 Android控件实现图片缩放功能,需要的朋友点击查看。

1.简介

话不多说先来张效果图

控件缩放移动.gif

上面的gif中,依次进行了拖动——>触摸右上角放大,缩小——>触摸上方与右测边缘——>双指放大缩小。

2 使用步骤

2.1 布局。外层一个LinearLayout,里面一个自定义的控件DragScaleView,为了能够更清楚的看到控件的变化过程,就给控件加了一个灰色带虚线的边框bg_dashgap。

layout文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:id="@+id/root"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#80ce3d3a"
 android:gravity="center_horizontal"
 android:fitsSystemWindows="true">
 <com.xxx.xxx.ui.DragScaleView
 android:id="@+id/hair_dv"
 android:src="@drawable/ic_sure"
 android:background="@drawable/bg_dashgap"
 android:adjustViewBounds="true"
 android:layout_marginLeft="50dp"
 android:layout_marginTop="10dp"
 android:layout_width="100dp"
 android:layout_height="120dp"
 android:clickable="true"/>
</LinearLayout>

在drawable文件夹下的bg_dashgap.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
 <!-- 圆角 -->
 <corners
 android:bottomLeftRadius="8dp"
 android:bottomRightRadius="8dp"
 android:radius="15dp"
 android:topLeftRadius="8dp"
 android:topRightRadius="8dp" />
 <!-- 描边 -->
 <stroke
 android:dashGap="4dp"
 android:dashWidth="4dp"
 android:width="2dp"
 android:color="@color/my_gery" />
</shape>

2.2 自定义的控件

单指触摸:

当ACTION_DOWN时如果坐标为1.2.3.4四个区域,则对View进行相应的左上/右上/左下/右下拉伸;

当ACTION_DOWN时如果坐标为5.6.7.8四个区域,则分别对上/右/下/左四个方向进行拉伸;

当ACTION_DOWN时如果坐标为9这个区域,则对View进行移动;

双指触摸:

先计算出触摸时双指的距离,float oriDist=distance(event);

再得到双指离开屏幕的距离,float newDist =distance(event);

得到两者之间的比例 float scale = newDist / oriDist;

计算双指间距离的方法

/**
 * 计算两个手指间的距离
 * @param event 触摸事件
 * @return 放回两个手指之间的距离
 */
 private float distance(MotionEvent event) {
 float x = event.getX(0) - event.getX(1);
 float y = event.getY(0) - event.getY(1);
 return (float) Math.sqrt(x * x + y * y);//两点间距离公式
 }

自定义的控件

onTouch(View v, MotionEvent event)的触摸事件中代码块

image.png

其他的关键地方,代码中都有比较详细的注释了。思路就是

触摸监听

判断不同情况---getDirection(v, (int) event.getX(), (int) event.getY())
计算得到新的oriLeft, oriTop, oriRight, oriBottom
重新绘制---v.layout(oriLeft, oriTop, oriRight, oriBottom)

3 DragScaleView 的完整代码

public class DragScaleView extends android.support.v7.widget.AppCompatImageView implements View.OnTouchListener {
 protected int screenWidth;
 protected int screenHeight;
 protected int lastX;
 protected int lastY;
 private int oriLeft;
 private int oriRight;
 private int oriTop;
 private int oriBottom;
 private int dragDirection;
 private static final int TOP = 0x15;
 private static final int LEFT = 0x16;
 private static final int BOTTOM = 0x17;
 private static final int RIGHT = 0x18;
 private static final int LEFT_TOP = 0x11;
 private static final int RIGHT_TOP = 0x12;
 private static final int LEFT_BOTTOM = 0x13;
 private static final int RIGHT_BOTTOM = 0x14;
 private static final int TOUCH_TWO = 0x21;
 private static final int CENTER = 0x19;
 private int offset = 0; //可超出其父控件的偏移量
 protected Paint paint = new Paint();
 private static final int touchDistance = 80; //触摸边界的有效距离
 // 初始的两个手指按下的触摸点的距离
 private float oriDis = 1f;
 /**
 * 初始化获取屏幕宽高
 */
 protected void initScreenW_H() {
 screenHeight = getResources().getDisplayMetrics().heightPixels - 40;
 screenWidth = getResources().getDisplayMetrics().widthPixels;
 }
 public DragScaleView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 setOnTouchListener(this);
 initScreenW_H();
 }
 public DragScaleView(Context context, AttributeSet attrs) {
 super(context, attrs);
 setOnTouchListener(this);
 initScreenW_H();
 }
 public DragScaleView(Context context) {
 super(context);
 setOnTouchListener(this);
 initScreenW_H();
 }
 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 paint.setColor(Color.GRAY);
 paint.setStrokeWidth(4.0f);
 paint.setStyle(Paint.Style.STROKE);
 }
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 setBackgroundResource(R.drawable.bg_dashgap);
 int action = event.getAction()& MotionEvent.ACTION_MASK;
 if (action == MotionEvent.ACTION_DOWN) {
 oriLeft = v.getLeft();
 oriRight = v.getRight();
 oriTop = v.getTop();
 oriBottom = v.getBottom();
 lastY = (int) event.getRawY();
 lastX = (int) event.getRawX();
 dragDirection = getDirection(v, (int) event.getX(),
  (int) event.getY());
 }
 if (action == MotionEvent.ACTION_POINTER_DOWN){
 oriLeft = v.getLeft();
 oriRight = v.getRight();
 oriTop = v.getTop();
 oriBottom = v.getBottom();
 lastY = (int) event.getRawY();
 lastX = (int) event.getRawX();
 dragDirection = TOUCH_TWO;
 oriDis = distance(event);
 }
 // 处理拖动事件
 delDrag(v, event, action);
 invalidate();
 return false;
 }
 /**
 * 处理拖动事件
 *
 * @param v
 * @param event
 * @param action
 */
 protected void delDrag(View v, MotionEvent event, int action) {
 switch (action) {
 case MotionEvent.ACTION_MOVE:
 int dx = (int) event.getRawX() - lastX;
 int dy = (int) event.getRawY() - lastY;
 switch (dragDirection) {
  case LEFT: // 左边缘
  left(v, dx);
  break;
  case RIGHT: // 右边缘
  right(v, dx);
  break;
  case BOTTOM: // 下边缘
  bottom(v, dy);
  break;
  case TOP: // 上边缘
  top(v, dy);
  break;
  case CENTER: // 点击中心-->>移动
  center(v, dx, dy);
  break;
  case LEFT_BOTTOM: // 左下
  left(v, dx);
  bottom(v, dy);
  break;
  case LEFT_TOP: // 左上
  left(v, dx);
  top(v, dy);
  break;
  case RIGHT_BOTTOM: // 右下
  right(v, dx);
  bottom(v, dy);
  break;
  case RIGHT_TOP: // 右上
  right(v, dx);
  top(v, dy);
  break;
  case TOUCH_TWO: //双指操控
  float newDist =distance(event);
  float scale = newDist / oriDis;
  //控制双指缩放的敏感度
  int distX = (int) (scale*(oriRight-oriLeft)-(oriRight-oriLeft))/50;
  int distY = (int) (scale*(oriBottom-oriTop)-(oriBottom-oriTop))/50;
  if (newDist>10f){//当双指的距离大于10时,开始相应处理
  left(v, -distX);
  top(v, -distY);
  right(v, distX);
  bottom(v, distY);
  }
  break;
 }
 if (dragDirection != CENTER) {
  v.layout(oriLeft, oriTop, oriRight, oriBottom);
 }
 lastX = (int) event.getRawX();
 lastY = (int) event.getRawY();
 break;
 case MotionEvent.ACTION_UP:
 case MotionEvent.ACTION_POINTER_UP:
 dragDirection = 0;
 break;
 }
 }
 /**
 * 触摸点为中心->>移动
 *
 * @param v
 * @param dx
 * @param dy
 */
 private void center(View v, int dx, int dy) {
 int left = v.getLeft() + dx;
 int top = v.getTop() + dy;
 int right = v.getRight() + dx;
 int bottom = v.getBottom() + dy;
 if (left < -offset) {
 left = -offset;
 right = left + v.getWidth();
 }
 if (right > screenWidth + offset) {
 right = screenWidth + offset;
 left = right - v.getWidth();
 }
 if (top < -offset) {
 top = -offset;
 bottom = top + v.getHeight();
 }
 if (bottom > screenHeight + offset) {
 bottom = screenHeight + offset;
 top = bottom - v.getHeight();
 }
 Log.d("raydrag", left+" "+top+" "+right+" "+bottom+" "+dx);
 v.layout(left, top, right, bottom);
 }
 /**
 * 触摸点为上边缘
 *
 * @param v
 * @param dy
 */
 private void top(View v, int dy) {
 oriTop += dy;
 if (oriTop < -offset) {
 //对view边界的处理,如果子view达到父控件的边界,offset代表允许超出父控件多少
 oriTop = -offset;
 }
 if (oriBottom - oriTop - 2 * offset < 200) {
 oriTop = oriBottom - 2 * offset - 200;
 }
 }
 /**
 * 触摸点为下边缘
 *
 * @param v
 * @param dy
 */
 private void bottom(View v, int dy) {
 oriBottom += dy;
 if (oriBottom > screenHeight + offset) {
 oriBottom = screenHeight + offset;
 }
 if (oriBottom - oriTop - 2 * offset < 200) {
 oriBottom = 200 + oriTop + 2 * offset;
 }
 }
 /**
 * 触摸点为右边缘
 *
 * @param v
 * @param dx
 */
 private void right(View v, int dx) {
 oriRight += dx;
 if (oriRight > screenWidth + offset) {
 oriRight = screenWidth + offset;
 }
 if (oriRight - oriLeft - 2 * offset < 200) {
 oriRight = oriLeft + 2 * offset + 200;
 }
 }
 /**
 * 触摸点为左边缘
 *
 * @param v
 * @param dx
 */
 private void left(View v, int dx) {
 oriLeft += dx;
 if (oriLeft < -offset) {
 oriLeft = -offset;
 }
 if (oriRight - oriLeft - 2 * offset < 200) {
 oriLeft = oriRight - 2 * offset - 200;
 }
 }
 /**
 * 获取触摸点flag
 *
 * @param v
 * @param x
 * @param y
 * @return
 */
 protected int getDirection(View v, int x, int y) {
 int left = v.getLeft();
 int right = v.getRight();
 int bottom = v.getBottom();
 int top = v.getTop();
 if (x < touchDistance && y < touchDistance) {
 return LEFT_TOP;
 }
 if (y < touchDistance && right - left - x < touchDistance) {
 return RIGHT_TOP;
 }
 if (x < touchDistance && bottom - top - y < touchDistance) {
 return LEFT_BOTTOM;
 }
 if (right - left - x < touchDistance && bottom - top - y < touchDistance) {
 return RIGHT_BOTTOM;
 }
 if (x < touchDistance) {
 return LEFT;
 }
 if (y < touchDistance) {
 return TOP;
 }
 if (right - left - x < touchDistance) {
 return RIGHT;
 }
 if (bottom - top - y < touchDistance) {
 return BOTTOM;
 }
 return CENTER;
 }
 /**
 * 计算两个手指间的距离
 *
 * @param event 触摸事件
 * @return 放回两个手指之间的距离
 */
 private float distance(MotionEvent event) {
 float x = event.getX(0) - event.getX(1);
 float y = event.getY(0) - event.getY(1);
 return (float) Math.sqrt(x * x + y * y);//两点间距离公式
 }
}

总结

以上所述是小编给大家介绍的Android控件的缩放移动功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

您可能感兴趣的文章:

  • Android通过ImageView设置手指滑动控件缩放
  • 学习使用Material Design控件(四)Android实现标题栏自动缩放、放大效果
  • Android通过自定义ImageView控件实现图片的缩放和拖动的实现代码
  • Android控件系列之相册Gallery&Adapter适配器入门&控件缩放动画入门
  • Android基于widget组件实现物体移动/控件拖动功能示例
  • Android自定义控件实现随手指移动的小球
(0)

相关推荐

  • Android控件系列之相册Gallery&Adapter适配器入门&控件缩放动画入门

    学习目的: 1.掌握在Android中如何建立Gallery 2.初步理解Android适配器的原理 3.实现简单的控件缩放动画 简介: 1.Gallery是Android内置的一个控件,它可以继承若干图片甚至是其他控件 2.Gallery自带了滚动播放图片功能,此功能您可以通过模拟器拖曳鼠标或者在手机上拖拽验证 3.Gallery需要适配器来传输数据,如果您不熟悉"适配器设计模式",可以将适配器理解为某厂商的电脑适配器,只要这个厂商的所有型号的电脑都能使用该适配器,也就是说,设计新型

  • Android自定义控件实现随手指移动的小球

    一个关于自定义控件的小Demo,随着手指移动的小球. 先看下效果图: 实现代码如下: 1.自定义控件类 package com.dc.customview.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import

  • Android通过ImageView设置手指滑动控件缩放

    ImageView设置手指滑动缩放效果,具体实现步骤大家通过本文学习下吧! 实现步骤 1, imageview设置scaletype为 android:scaleType="matrix" 2, 设置imageview的setOnTouchListener,重写里面的代码 3, 新建一个matrix, matrix.postScale(scale,scale,缩放中心,缩放中心); image.setImageMatrix(matrix); 这样image的大小就会改变了. 需要注意的

  • Android基于widget组件实现物体移动/控件拖动功能示例

    本文实例讲述了Android基于widget组件实现物体移动/控件拖动功能.分享给大家供大家参考,具体如下: package com.sky; import android.app.Activity; import android.os.Bundle; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickLi

  • 学习使用Material Design控件(四)Android实现标题栏自动缩放、放大效果

    本文要实现内容移动时,标题栏自动缩放/放大的效果,效果如下: 控件介绍 这次需要用到得新控件比较多,主要有以下几个: CoordinatorLayout 组织它的子views之间协作的一个Layout,它可以给子View切换提供动画效果. AppBarLayout 可以让包含在其中的控件响应被标记了ScrollingViewBehavior的View的滚动事件 CollapsingToolbarLayout 可以控制包含在CollapsingToolbarLayout其中的控件,在响应colla

  • Android通过自定义ImageView控件实现图片的缩放和拖动的实现代码

    概述:通过自定义ImageView控件,在xml布局里面调用自定的组件实现图片的缩放. /** * 自定义的ImageView控制,可对图片进行多点触控缩放和拖动 * * @author qiuwanyong */ public class MyImageView extends ImageView { /** * 初始化状态常量 */ public static final int STATUS_INIT = 1; /** * 图片放大状态常量 */ public static final i

  • Android实现控件的缩放移动功能

    上篇文章给大家介绍了 Android控件实现图片缩放功能,需要的朋友点击查看. 1.简介 话不多说先来张效果图 控件缩放移动.gif 上面的gif中,依次进行了拖动-->触摸右上角放大,缩小-->触摸上方与右测边缘-->双指放大缩小. 2 使用步骤 2.1 布局.外层一个LinearLayout,里面一个自定义的控件DragScaleView,为了能够更清楚的看到控件的变化过程,就给控件加了一个灰色带虚线的边框bg_dashgap. layout文件 <?xml version=&

  • Android输入框控件ClearEditText实现清除功能

    本文给大家带来一个很实用的小控件ClearEditText,就是在Android系统的输入框右边加入一个小图标,点击小图标可以清除输入框里面的内容,IOS上面直接设置某个属性就可以实现这一功能,但是Android原生EditText不具备此功能,所以要想实现这一功能我们需要重写EditText,接下来就带大家来实现这一小小的功能 我们知道,我们可以为我们的输入框在上下左右设置图片,所以我们可以利用属性android:drawableRight设置我们的删除小图标,如图 我这里设置了左边和右边的图

  • Android编程实现点击EditText之外的控件隐藏软键盘功能

    本文实例讲述了Android编程实现点击EditText之外的控件隐藏软键盘功能.分享给大家供大家参考,具体如下: 工具类 ... public static void hideKeyboard(Context ctx) { if (ctx != null) { View view = ((Activity) ctx).getCurrentFocus(); if (view != null) { InputMethodManager inputManager = (InputMethodMana

  • Android Service控件用法实例分析

    本文实例讲述了Android Service控件用法.分享给大家供大家参考,具体如下: 1.Service是一个应用程序的组件 2.Service没有图形化界面 3.用来处理耗时比较长的功能(下载.播放MP3) 4.更新ContentProvider.Intent以及系统的启动 Servcie不是一个单独的进程,不是一个线程 定义一个Service比较简单,只要继承Service类,实现其生命周期的方法即可.一个定义好的Service必须在AndroidManifest.xml文件中通过<ser

  • Android常见控件使用详解

    本文实例为大家分享了六种Android常见控件的使用方法,供大家参考,具体内容如下 1.TextView 主要用于界面上显示一段文本信息 2.Button 用于和用户交互的一个按钮控件 //为Button点击事件注册一个监听器 public class Click extends Activity{ private Button button; @Override ptotected void onCreate(Bundle savedInstanceState) { super.onCreat

  • Android UI控件之ImageSwitcher实现图片切换效果

    本文实例为大家分享了geSwitcher实现图片切换效果的具体代码,供大家参考,具体内容如下 从该名字就可以看出来,ImageSwitcher是一个图片切换控件,可以在一系列的图片中,逐张的显示特定的图片,利用该控件可以实现图片浏览器中的上一张,下一张的功能.其使用方法也较 为简单,不过需要注意的是ImageSwitcher在使用的时候需要一个ViewFactory,用来区分显示图片的容器和他的父窗口. 具体的用法直接看实例,照例,先上效果图 看看下一张的效果: 布局文件就不多谈了直接看Main

  • Android布局控件View ViewRootImpl WindowManagerService关系

    目录 1. View,ViewRoot和WindowManager简单介绍 1.1 View和ViewGroup 1.2 ViewRootImpl 1.3 WindowManager 2. ViewRootImpl的起源 2.1 ViewRootImpl创建时机 2.2 ViewRootImpl通知注册Window 3.ViewRootImpl与WindowManagerService的通信 3.1 WindowSession 3.2 IWindow 4. ViewRootImpl与View 1

  • Android设置控件阴影的三种方法

    本文实例为大家分享了Android设置控件阴影的方法,供大家参考,具体内容如下 第一种方式:elevation View的大小位置都是通过x,y确定的,而现在有了z轴的概念,而这个z值就是View的高度(elevation),而高度决定了阴影(shadow)的大小. View Elevation(视图高度) View的z值由两部分组成,elevation和translationZ(它们都是Android L新引入的属性). eleavation是静态的成员,translationZ是用来做动画.

  • VUE饿了么树形控件添加增删改功能的示例代码

    本文介绍了VUE饿了么树形控件添加增删改功能的示例代码,分享给大家,具体如下: element-ui树形控件:地址 在原文档中有个案例是有新增和删除功能,但是后来发现其修改的数据并不能直接影响到树形数据,所以采用了 render-content 的API重新写了个组件. 写个开发的步骤,所以文章比较长emmm 大致效果如图: 1.省市API 在网上复制了个省市的list,有两个属性是新增的 isEdit :控制编辑状态 maxexpandId :为现下id的最大值 export default{

  • Android AutoCompleteTextView控件基本用法示例

    本文实例讲述了Android AutoCompleteTextView控件基本用法.分享给大家供大家参考,具体如下: 当输入部分内容之后会有相关的建议,类似于百度提示信息 1.在布局文件中声明一个AutoCompleteTextView <AutoCompleteTextView android:id="@+id/autocomplete_country" android:layout_width="fill_parent" android:layout_he

随机推荐