自定义relative实现三层图,最上面一层图可旋转

package com.app.fantasticbaby;


import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout;


/** 
 * @author 作者 E-mail: 
 * @version 创建时间:2016-5-30 下午5:57:05 
 * 类说明 
 */
public class BottomAndTopView extends RelativeLayout {
  
private ImageView bottomIv;
private ImageView topIv;


private Drawable backgroud;
private Drawable bottomDrawable;
private Drawable topDrawable;
private LayoutParams buttomParams;
private LayoutParams topParams;
Matrix matrixTop = new Matrix();
Matrix savedMatrixTop = new Matrix();
Matrix matrixBottom = new Matrix();
Matrix savedMatrixBottom = new Matrix();
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
static final int ROATE = 3;
static final float MAX_SCALE = 2.0f;
static final float MIN_SCALE = 0.5f;
static float currentScale = 1.0f;
int mode = NONE;
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
float x_down = 0;
float y_down = 0;
float cx_down = 0;
float cy_down = 0;
private float degree;// 偏转角度
Point centerPoint = new Point();
float centerX;
float centerY;
private RelativeLayout rLayout;
@SuppressLint("NewApi")
public BottomAndTopView(Context context, AttributeSet attrs) {
super(context, attrs);
rLayout = this;
// 自定义属性获取
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.customView);
bottomDrawable = ta.getDrawable(R.styleable.customView_bottomRes);


topDrawable = ta.getDrawable(R.styleable.customView_topRes);


backgroud = ta.getDrawable(R.styleable.customView_backgroud);
ta.recycle();
setBackground(backgroud);
// 设置属性值
bottomIv = new ImageView(context);
bottomIv.setImageDrawable(bottomDrawable);
// 设置属性值
topIv = new ImageView(context);
topIv.setImageDrawable(topDrawable);
// 设置底部图片规则
buttomParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
buttomParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);
bottomIv.setScaleType(ScaleType.CENTER_INSIDE);
addView(bottomIv, buttomParams);
bottomIv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
bottomIv.setScaleType(ScaleType.MATRIX);


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


case MotionEvent.ACTION_DOWN:


Log.w("FLAG", "ACTION_DOWN");
x_down = event.getX();
y_down = event.getY();
matrixBottom.set(bottomIv.getImageMatrix());
savedMatrixBottom.set(matrixBottom);
start.set(x_down, y_down);
mode = ROATE;
break;
case MotionEvent.ACTION_UP:
Log.w("FLAG", "ACTION_UP");
case MotionEvent.ACTION_POINTER_UP:
Log.w("FLAG", "ACTION_POINTER_UP");
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
cx_down = event.getX();
cy_down = event.getY();
Log.w("FLAG", "ACTION_MOVE");
if (mode == ROATE) {


// 更新中心坐标
updateCenterPoint(topIv);
matrixBottom.set(savedMatrixBottom);
resetPointAngle();


matrixBottom.postRotate(degree,
bottomIv.getWidth() / 2,
bottomIv.getHeight() / 2);// 旋轉();
}
break;
}
bottomIv.setImageMatrix(matrixBottom);
return true;
}
});
// 设置上层图片规则
topParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
topParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);
topIv.setScaleType(ScaleType.CENTER_INSIDE);
addView(topIv, topParams);


topIv.setOnTouchListener(new OnTouchListener() {


@Override
public boolean onTouch(View v, MotionEvent event) {
topIv.setScaleType(ScaleType.MATRIX);


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


case MotionEvent.ACTION_DOWN:


Log.w("FLAG", "ACTION_DOWN");
x_down = event.getX();
y_down = event.getY();
matrixTop.set(topIv.getImageMatrix());
savedMatrixTop.set(matrixTop);
start.set(x_down, y_down);
// 更新中心坐标
updateCenterPoint(topIv);
if (Math.abs(centerX - x_down) < 40
&& Math.abs(centerY - y_down) < 40) {
mode = DRAG;
} else {
mode = ROATE;
}
break;
case MotionEvent.ACTION_UP:
Log.w("FLAG", "ACTION_UP");
case MotionEvent.ACTION_POINTER_UP:
Log.w("FLAG", "ACTION_POINTER_UP");
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
cx_down = event.getX();
cy_down = event.getY();
Log.w("FLAG", "ACTION_MOVE");
if (mode == ROATE) {


// 更新中心坐标
updateCenterPoint(topIv);
matrixTop.set(savedMatrixTop);
resetPointAngle();


matrixTop.postRotate(degree, topIv.getWidth() / 2,
topIv.getHeight() / 2);// 旋轉();


topIv.setImageMatrix(matrixTop);
} else if (mode == DRAG) {


// 更新中心坐标
rLayout.setTranslationX(cx_down - start.x);
rLayout.setTranslationY(cy_down - start.y);
}
break;
}
return true;


}
});
}


@SuppressLint("NewApi")
@Override
public boolean onTouchEvent(MotionEvent event) {
this.topIv.setScaleType(ScaleType.MATRIX);
this.bottomIv.setScaleType(ScaleType.MATRIX);


float scale = 0;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
Log.w("FLAG", "ACTION_UP");
case MotionEvent.ACTION_POINTER_UP:
Log.w("FLAG", "ACTION_POINTER_UP");
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
cx_down = event.getX();
cy_down = event.getY();
Log.w("FLAG", "ACTION_MOVE");
if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
scale = newDist / oldDist;
this.setScaleX(scale);
this.setScaleY(scale);
}
}
break;
}
topIv.setImageMatrix(matrixTop);
bottomIv.setImageMatrix(matrixBottom);
return true;
}
/**
* 更新转盘中心坐标
*/
@SuppressLint("NewApi")
private void updateCenterPoint(ImageView view) {
centerPoint.x = view.getLeft() + view.getWidth() / 2;
// // 当前图片中心纵坐标
centerPoint.y = view.getTop() + view.getHeight() / 2;
// 获取imageview控件中图片实际坐标
Matrix matrix = view.getMatrix();
float[] value = new float[9];
matrix.getValues(value);
// view.getDrawable().getBounds().width() 2 获得imageview中图片之际宽度
centerX = value[2] + view.getDrawable().getBounds().width() / 2;
// // // 当前图片中心纵坐标
centerY = value[5] + view.getDrawable().getBounds().height() / 2;
}


/**

* 方法名:resetPointAngle 功能:重新计算每个点的角度 参数:

*/
private void resetPointAngle() {
// 每次转动的角度
degree = computeMigrationAngle();


}


/**

* 方法名:computeMigrationAngle 功能:计算偏移角度 参数: 每次转动的角度差
*/
private float computeMigrationAngle() {


/**
* Math.PI 记录的圆周率 Math.E记录e的常量 Math.abs 求绝对值 Math.sin 正弦函数
* Math.asin反正弦函数 Math.cos 余弦函数 Math.acos 反余弦函数 Math.tan 正切函数 Math.atan
* 反正切函数&nbsp; Math.atan2 商的反正切函数 Math.toDegrees 弧度转化为角度 Math.toRadians
* 角度转化为弧度 Math.ceil 得到不小于某数的最大整数 Math.floor 得到不大于某数的最大整数
*/
return (float) (Math.toDegrees(Math.atan2(cy_down - centerPoint.y,
cx_down - centerPoint.x)) - Math.toDegrees(Math.atan2(y_down
- centerPoint.y, x_down - centerPoint.x)));
}


private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}


private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}


@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {


boolean isIntercept = false;
switch (ev.getAction() & MotionEvent.ACTION_MASK) {


case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(ev);
if (oldDist > 10f) {
savedMatrixTop.set(matrixTop);
savedMatrixBottom.set(matrixBottom);
midPoint(mid, ev);
mode = ZOOM;
}
isIntercept = true;
break;
}
return isIntercept;
}

}

布局文件:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@drawable/back1" >


    <com.app.fantasticbaby.BottomAndTopView
        
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:bottomRes="@drawable/back2"
        custom:topRes="@drawable/back3" />


</LinearLayout>

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值