代码之家  ›  专栏  ›  技术社区  ›  VirtualProdigy

基于触摸位置的放大

  •  0
  • VirtualProdigy  · 技术社区  · 11 年前

    我在Android中开发基于触摸位置的放大率时遇到了问题。我想要的结果类似于旧的macbook应用程序栏放大;鼠标悬停在其上的图标放大最大,周围的图标慢慢缩小到原来的大小。

    我已经在图标栏的中心添加了一幅用户触摸图标时的图像。

    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布局

    <?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 回复  |  直到 11 年前
        1
  •  0
  •   VirtualProdigy    11 年前

    我的解决方案是一个简单得多的方程式。
    我使用每个正方形的中心轴来获得它们与中心的距离,然后将与中心的间距除以布局高度。

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

    中心越靠近,刻度越大,反之,刻度减小,但从不低于1。

    推荐文章