我在Android中基于触摸位置开发放大率时遇到了问题。我想要的结果类似于旧的Mac书应用栏放大;鼠标悬停在上方的图标是放大的最大图标,图标环绕它,缩小到原始大小。
如果用户触摸图标栏中心的图标,我会附上一张图片。
目前我的代码有点有效。我使用cos方程来创建比例因子,但是当您触摸黄色图标附近时,它会导致最后一个绿色图标放大。倾斜的影响也不恰当。我附上了一张带有样品触摸和代码的照片。 感谢您提供任何帮助。
Java类预先形成缩放
public class Layout extends RelativeLayout implements View.OnTouchListener{
private Camera mCamera = new Camera();
private Matrix mMatrix = new Matrix();
private ArrayList<Layer> layers = new ArrayList<Layer>();
private final String TAG = this.getClass().getSimpleName();
private int xTouch = 0;
private int yTouch = 0;
private boolean isUserInput = false;
private int childHeight = 1;
private Context context;
public TrackerLayout(Context context) {
super(context);
setupView(context);
}
public TrackerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setupView(context);
}
public TrackerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupView(context);
}
private void setupView(Context context){
this.context = context;
setOnTouchListener(this);
setWillNotDraw(false);
}
@Override
protected void onDraw(Canvas canvas) {
if (layers.size() != getChildCount()) {
getChildrenViews();
}
//getChild's order
sortChildrenByDist();
super.onDraw(canvas);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
childHeight = h / 8;
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if(isUserInput && yTouch >= 0) {
Bitmap bitmap = child.getDrawingCache();
if (bitmap == null) {
child.setDrawingCacheEnabled(true);
child.buildDrawingCache();
bitmap = child.getDrawingCache();
}
//Get a reference for the child layer that's being modified
Layer layer = null;
for (Layer tempLayer : layers) {
if (tempLayer.child.getId() == child.getId()) {
layer = tempLayer;
break;
}
}
canvas.save();
if(layer.coordinates.scale < 1){
layer.coordinates.scale = 1;
}
canvas.scale(layer.coordinates.scale, layer.coordinates.scale, layer.coordinates.pivotX, layer.coordinates.pivotY);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
if (mCamera == null) {
mCamera = new Camera();
}
mCamera.save();
mCamera.rotateY(layer.coordinates.rotation);
if (mMatrix == null) {
mMatrix = new Matrix();
}
mCamera.getMatrix(mMatrix);
mCamera.restore();
mMatrix.preTranslate(-layer.coordinates.centerX, -layer.coordinates.centerY);
mMatrix.postScale(layer.coordinates.scale, layer.coordinates.scale);
mMatrix.postTranslate(layer.coordinates.pivotX, layer.coordinates.pivotY);
canvas.drawBitmap(bitmap, layer.coordinates.left, layer.coordinates.top, paint);
canvas.restore();
return false;
}
return super.drawChild(canvas, child, drawingTime);
}
private void getChildrenViews() {
int childrenCount = this.getChildCount();
for (int i = 0; i < childrenCount; i++) {
if (getChildAt(i) instanceof ImageView) {
Layer layer = new Layer();
ImageView child = (ImageView) getChildAt(i);
int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, context.getResources().getDisplayMetrics());
RelativeLayout.LayoutParams params = (LayoutParams) child.getLayoutParams();
params.height = childHeight;
child.setLayoutParams(params );
layer.child = (child);
layers.add(layer);
}
}
}
private void sortChildrenByDist() {
ArrayList<Layer> negDistLayers = new ArrayList<Layer>();
ArrayList<Layer> postDistLayers = new ArrayList<Layer>();
for (Layer layer : layers) {
layer.coordinates = calculateCoordinates(layer.child);
if(layer.coordinates.distFromCenter >= 0 ){
postDistLayers.add(layer);
}else{
negDistLayers.add(layer);
}
}
Collections.sort(negDistLayers);
Collections.sort(postDistLayers);
layers.clear();
layers.addAll(postDistLayers);
layers.addAll(negDistLayers);
drawOrderedLayers();
}
private synchronized void drawOrderedLayers() {
for (int i = (layers.size() - 1); i > -1; i--) {
this.bringChildToFront(layers.get(i).child);
}
}
/**
* This method calculates the coordinates used to create the rotates, camera, and scaling on each child view
*
* @param child - the view the coordinates will be calculated from
* @return
*/
private Coordinates calculateCoordinates(View child) {
Coordinates coordinates = new Coordinates();
coordinates.left = child.getLeft();
coordinates.top = child.getTop();
coordinates.centerX = child.getWidth() / 2;
coordinates.centerY = child.getHeight() / 2;
coordinates.pivotX = coordinates.left + coordinates.centerX;
coordinates.pivotY = coordinates.top + coordinates.centerY;
coordinates.userYInput = yTouch;
coordinates.distFromCenter = (yTouch == 0) ? coordinates.pivotY : ((coordinates.pivotY - coordinates.userYInput) / coordinates.userYInput);
double cosValue = (Math.cos(coordinates.distFromCenter));
coordinates.scale = (float) (2 * cosValue);
coordinates.rotation = coordinates.distFromCenter;
return coordinates;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
final int action = event.getAction();
Log.i(TAG, " on touch detected");
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
xTouch = (int) event.getX();
yTouch = (int) event.getY();
isUserInput = true;
return true;
}
case MotionEvent.ACTION_MOVE: {
xTouch = (int) event.getX();
yTouch = (int) event.getY();
isUserInput = true;
return true;
}
default:
isUserInput = false;
return false;
}
}
private class Coordinates {
int left;
int top;
int centerX;
int centerY;
float pivotX;
float pivotY;
float userYInput;
float distFromCenter;
float scale;
float rotation;
}
//This class will hold a reference to the child and it's coordinates to
//help imitate layers
private class Layer implements Comparable<Layer> {
View child;
Coordinates coordinates;
//All values need to be sort towards ) so there's an if case to determine if the input is
//comparing the list of positive values or negative values
public int compareTo(Layer compareItem) {
if(coordinates.distFromCenter >= 0) {
return Float.compare(coordinates.distFromCenter, compareItem.coordinates.distFromCenter);
}else{
return Float.compare(compareItem.coordinates.distFromCenter, coordinates.distFromCenter);
}
}
}
}
xml layout
<?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"
android:background="@color/background_color">
<com.layouts.Layout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop=“true”
android:orientation="vertical">
<ImageView
android:id="@+id/icon_level_1"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:layout_alignParentRight="true"
android:background="#FFF66C"
android:layout_alignParentTop="true"/>
<ImageView
android:id="@+id/icon_level_2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#E7EE6C"
android:layout_alignParentRight="true"
android:layout_below="@+id/ticon_level_1"/>
<ImageView
android:id="@+id/icon_level_3"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#CCE46D"
android:layout_alignParentRight="true"
android:layout_below="@+id/icon_level_2"/>
<ImageView
android:id="@+id/icon_level_4"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#B2E07B"
android:layout_alignParentRight="true"
android:layout_below="@+id/icon_level_3"/>
<ImageView
android:id="@+id/icon_level_5"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#8BDB91"
android:layout_alignParentRight="true"
android:layout_below="@+id/icon_level_4"/>
<ImageView
android:id="@+id/icon_level_6"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#65BE91"
android:layout_alignParentRight="true"
android:layout_below="@+id/icon_level_5"/>
<ImageView
android:id="@+id/icon_level_7"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#4E8F77"
android:layout_alignParentRight="true"
android:layout_below="@+id/icon_level_6"/>
<ImageView
android:id="@+id/icon_level_8"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#3A655F"
android:layout_alignParentRight="true"
android:layout_below="@+id/icon_level_7"/>
</com.layouts.Layout>
答案 0 :(得分:0)
我对此的解决方案是一个更为简单的方程式 我使用每个方块的中心枢轴来获取它们与中心的距离,然后将距离中心的距离除以布局高度。
distFromCenter = (yTouch == 0) ? pivotY : Math.abs((pivotY - userYInput));
scale = (distFromCenter / layoutHieght);
scale = scale == 0 ? 2 : 2 - scale.
关闭中心,比例越大,另一方面它减少但从未低于1。