基于触摸位置的放大率

时间:2015-02-26 18:50:16

标签: android layout image-scaling magnification

我在Android中基于触摸位置开发放大率时遇到了问题。我想要的结果类似于旧的Mac书应用栏放大;鼠标悬停在上方的图标是放大的最大图标,图标环绕它,缩小到原始大小。

如果用户触摸图标栏中心的图标,我会附上一张图片。

enter image description here

目前我的代码有点有效。我使用cos方程来创建比例因子,但是当您触摸黄色图标附近时,它会导致最后一个绿色图标放大。倾斜的影响也不恰当。我附上了一张带有样品触摸和代码的照片。 感谢您提供任何帮助。 enter image description here

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>

1 个答案:

答案 0 :(得分:0)

我对此的解决方案是一个更为简单的方程式 我使用每个方块的中心枢轴来获取它们与中心的距离,然后将距离中心的距离除以布局高度。

 distFromCenter = (yTouch == 0) ? pivotY : Math.abs((pivotY - userYInput));
 scale = (distFromCenter / layoutHieght);
 scale = scale == 0 ? 2 : 2 - scale. 

关闭中心,比例越大,另一方面它减少但从未低于1。