捏缩放Android中的LinearLayout

时间:2016-07-14 06:48:39

标签: android

我需要缩放整个布局包含Image,TextViews等。我发现缩放功能仅适用于Imageview。

4 个答案:

答案 0 :(得分:1)

默认情况下,布局没有缩放功能。 我资助了这个,https://code.google.com/archive/p/android-zoom-view/downloads

在这个答案中,用户解释了如何使用它。 https://stackoverflow.com/a/15850113/6093353

希望这能帮到你!

答案 1 :(得分:1)

创建一个名为Layout的自定义ZoomeLinearLayout类。

<强> ZoomLinearLayout.java

public class ZoomLinearLayout extends LinearLayout implements ScaleGestureDetector.OnScaleGestureListener {

    private enum Mode {
        NONE,
        DRAG,
        ZOOM
    }

    private static final float MIN_ZOOM = 1.0f;
    private static final float MAX_ZOOM = 4.0f;

    private Mode mode = Mode.NONE;
    private float scale = 1.0f;
    private float lastScaleFactor = 0f;

    private float startX = 0f;
    private float startY = 0f;

    private float dx = 0f;
    private float dy = 0f;
    private float prevDx = 0f;
    private float prevDy = 0f;

    public ZoomLinearLayout(Context context) {
        super(context);
        init(context);
    }

    public ZoomLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ZoomLinearLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public void init(Context context) {
        final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
        this.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        if (scale > MIN_ZOOM) {
                            mode = Mode.DRAG;
                            startX = motionEvent.getX() - prevDx;
                            startY = motionEvent.getY() - prevDy;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mode == Mode.DRAG) {
                            dx = motionEvent.getX() - startX;
                            dy = motionEvent.getY() - startY;
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        mode = Mode.ZOOM;
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = Mode.DRAG;
                        break;
                    case MotionEvent.ACTION_UP:
                        mode = Mode.NONE;
                        prevDx = dx;
                        prevDy = dy;
                        break;
                }
                scaleDetector.onTouchEvent(motionEvent);

                if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                    float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
                    float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
                    dx = Math.min(Math.max(dx, -maxDx), maxDx);
                    dy = Math.min(Math.max(dy, -maxDy), maxDy);
                    applyScaleAndTranslation();
                }

                return true;
            }
        });
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector scaleDetector) {
        float scaleFactor = scaleDetector.getScaleFactor();
        if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
            scale *= scaleFactor;
            scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
            lastScaleFactor = scaleFactor;
        } else {
            lastScaleFactor = 0;
        }
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector scaleDetector) {
    }

    private void applyScaleAndTranslation() {
        child().setScaleX(scale);
        child().setScaleY(scale);
        child().setTranslationX(dx);
        child().setTranslationY(dy);
    }

    private View child() {
        return getChildAt(0);
    }

}

然后在Layout文件中,使用LinearLayout包裹您想要缩放的ZoomLinearLayout请注意,ZoomLinearLayout只有一个直接子女。

 <com.asif.test.ZoomLinearLayout
    android:layout_width="match_parent"
    android:id="@+id/zoom_linear_layout"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </LinearLayout>

</com.asif.test.ZoomLinearLayout>

现在在Activity中,创建ZoomLinearLayout对象并为其设置onTouch()事件。

final ZoomLinearLayout zoomLinearLayout = (ZoomLinearLayout) findViewById(R.id.zoom_linear_layout);
zoomLinearLayout.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        zoomLinearLayout.init(MainActivity.this);
        return false;
    }
});

答案 2 :(得分:1)

创建一个名为ZoomLayout的自定义布局类。在这个布局中,我使用了Framelayout,你可以扩展所有智能布局。

ZoomLayout.java

public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {

private enum Mode {
    NONE,
    DRAG,
    ZOOM
}

private static final String TAG = "ZoomLayout";
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 16.0f;

private Mode mode = Mode.NONE;
private float scale = 1.0f;
private float lastScaleFactor = 0f;

// Where the finger first  touches the screen
private float startX = 0f;
private float startY = 0f;

// How much to translate the canvas
private float dx = 0f;
private float dy = 0f;
private float prevDx = 0f;
private float prevDy = 0f;
ZoomViewListener listener;
public ZoomLayout(Context context) {
    super(context);
    init(context);
    setListner(getListener());
}

public ZoomLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
    setListner(getListener());
}

public ZoomLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
    setListner(getListener());

}

private void init(Context context) {
    final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
    this.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:






                    /*float eventX = motionEvent.getX();
                    float eventY = motionEvent.getY();
                    float[] eventXY = new float[]{eventX, eventY};

// float [] src = {motionEvent.getX(),motionEvent.getY()}; // float [] dst = new float [2];

                    Matrix invertMatrix = new Matrix();
                    ((ImageView) getChildAt(1)).getImageMatrix().invert(invertMatrix);

                    invertMatrix.mapPoints(eventXY);
                    //invertMatrix.mapPoints(src,dst);
                    int x = Integer.valueOf((int) eventXY[0]);
                    int y = Integer.valueOf((int) eventXY[1]);


                    Log.e("image x", "===img ki x==" + x);
                    Log.e("image y", "===img ki y==" + y);

                    Drawable imgDrawable = ((ImageView) getChildAt(1)).getDrawable();
                    Bitmap bitmap = ((BitmapDrawable) imgDrawable).getBitmap();

                   // int color_value= getHitboxColour(x,y,(ImageView) getChildAt(0));

//限制位图中的x,y范围

                    if (x < 0) {
                        x = 0;
                    } else if (x > bitmap.getWidth() - 1) {
                        x = bitmap.getWidth() - 1;
                    }

                    if (y < 0) {
                        y = 0;
                    } else if (y > bitmap.getHeight() - 1) {
                        y = bitmap.getHeight() - 1;
                    }


                    //Log.e("touched color: ", "" + "#" + Integer.toHexString(color_value));
                   int touchedRGB = bitmap.getPixel(x, y);

                    int redValue = Color.red(touchedRGB);
                    int blueValue = Color.blue(touchedRGB);
                    int greenValue = Color.green(touchedRGB);

                    Log.e("touched color: ", "" + "#" + Integer.toHexString(touchedRGB));

                    listener.onPlaceChosen(touchedRGB);*/

                    Log.i(TAG, "DOWN");
                    if (scale > MIN_ZOOM) {
                        mode = Mode.DRAG;
                        startX = motionEvent.getX() - prevDx;
                        startY = motionEvent.getY() - prevDy;
                    }





                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == Mode.DRAG) {
                        dx = motionEvent.getX() - startX;
                        dy = motionEvent.getY() - startY;

                    }
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    mode = Mode.ZOOM;
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    mode = Mode.DRAG;
                    break;
                case MotionEvent.ACTION_UP:
                    Log.i(TAG, "UP");
                    mode = Mode.NONE;
                    prevDx = dx;
                    prevDy = dy;
                    break;
            }
            scaleDetector.onTouchEvent(motionEvent);

           /* if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
                getParent().requestDisallowInterceptTouchEvent(true);
                float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
                float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
                dx = Math.min(Math.max(dx, -maxDx), maxDx);
                dy = Math.min(Math.max(dy, -maxDy), maxDy);
                Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx
                        + ", max " + maxDx);
                applyScaleAndTranslation();

            }*/

            if (( scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
                getParent().requestDisallowInterceptTouchEvent(true);
                float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
                float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
                dx = Math.min(Math.max(dx, -maxDx), maxDx);
                dy = Math.min(Math.max(dy, -maxDy), maxDy);
               // Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx);
               // applyScaleAndTranslation();
                child().setScaleX(scale);
                child().setScaleY(scale);

                float maxDx1 = (child2().getWidth() - (child2().getWidth() / scale)) / 2 * scale;
                float maxDy1 = (child2().getHeight() - (child2().getHeight() / scale)) / 2 * scale;
                dx = Math.min(Math.max(dx, -maxDx1), maxDx1);
                dy = Math.min(Math.max(dy, -maxDy1), maxDy1);
               // Log.i(TAG, "Width: " + child2().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx1);
                // applyScaleAndTranslation();
                child2().setScaleX(scale);
                child2().setScaleY(scale);


            }

            if(mode == Mode.DRAG ){
                getParent().requestDisallowInterceptTouchEvent(true);
                float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
                float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
                dx = Math.min(Math.max(dx, -maxDx), maxDx);
                dy = Math.min(Math.max(dy, -maxDy), maxDy);
               // Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx);

                child().setTranslationX(dx);
                child().setTranslationY(dy);


                getParent().requestDisallowInterceptTouchEvent(true);
                float maxDx1 = (child2().getWidth() - (child2().getWidth() / scale)) / 2 * scale;
                float maxDy1 = (child2().getHeight() - (child2().getHeight() / scale)) / 2 * scale;
                dx = Math.min(Math.max(dx, -maxDx1), maxDx1);
                dy = Math.min(Math.max(dy, -maxDy1), maxDy1);
               // Log.i(TAG, "Width: " + child2().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx);

                child2().setTranslationX(dx);
                child2().setTranslationY(dy);
            }



            return true;
        }
    });
}
public int getHitboxColour(int x, int y,ImageView iv) {

   // ImageView iv = (ImageView) findViewById(R.id.img_hitbox);

    Bitmap bmpHotspots;

    int pixel;

//通过定位屏幕元素(如活动标题栏)来修复任何偏移。

//当我测试Bill Lahti的代码时,这部分导致了我的问题。

    int[] location = new int[2];

    iv.getLocationOnScreen(location);

    x -= location[0];

    y -= location[1];

//防止崩溃,返回背景噪音

    if ((x < 0) || (y < 0)) {

        return Color.WHITE;

    }

//将缩放后的位图绘制到内存中

    iv.setDrawingCacheEnabled(true);

    bmpHotspots = Bitmap.createBitmap(iv.getDrawingCache());

    iv.setDrawingCacheEnabled(false);



    pixel = bmpHotspots.getPixel(x, y);

    bmpHotspots.recycle();

    return pixel;

}
// ScaleGestureDetector

@Override
public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
    Log.i(TAG, "onScaleBegin");
    return true;
}

@Override
public boolean onScale(ScaleGestureDetector scaleDetector) {
    float scaleFactor = scaleDetector.getScaleFactor();
    Log.i(TAG, "onScale" + scaleFactor);
    if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
        scale *= scaleFactor;
        scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
        lastScaleFactor = scaleFactor;
    } else {
        lastScaleFactor = 0;
    }
    return true;
}

@Override
public void onScaleEnd(ScaleGestureDetector scaleDetector) {
    Log.i(TAG, "onScaleEnd");
}

private void applyScaleAndTranslation() {
    child().setScaleX(scale);
    child().setScaleY(scale);
    child().setTranslationX(dx);
    child().setTranslationY(dy);




}

private View child() {
    return getChildAt(0);
}


private View child2() {
    return getChildAt(1);
}
public interface ZoomViewListener {

    void onZoomStarted(float zoom, float zoomx, float zoomy);

    void onZooming(float zoom, float zoomx, float zoomy);

    void onZoomEnded(float zoom, float zoomx, float zoomy);

    void onPlaceChosen(int color);
}
public ZoomViewListener getListener() {
    return listener;
}

public void setListner(final ZoomViewListener listener) {
    this.listener = listener;
}}

答案 3 :(得分:0)

Xml其中布局

   <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_marginBottom="20dp"
    android:layout_centerHorizontal="true"
    android:id="@+id/llzoom"
    android:orientation="vertical">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/ic_launcher"/>
    <TextView
        android:id="@+id/text"
        android:layout_width="100dp"
        android:layout_height="100dp"

        android:layout_marginTop="20dp"

        android:text="School"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        android:textColor="@android:color/black"
        android:textStyle="bold" />
     </LinearLayout>

导入

import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
  

用于缩小动画

   findViewById(R.id.llzoom).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Animation zoomout = AnimationUtils.loadAnimation(SelectBuyerActivity.this, R.anim.zoomout);
            findViewById(R.id.llzoom).startAnimation(zoomout);
        }
    });
  

res / anim文件夹中的动画

<强> zoomout.xml

<scale  xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/bounce_interpolator" 
 android:fromXScale="0.5" 
 android:toXScale="1" 
 android:fromYScale="0.5" 
 android:toYScale="1" 
 android:pivotX="50%" 
 android:pivotY="50%" 
 android:duration="500" 
 android:fillAfter="true">
 </scale>
  

您还使用了更多动画,例如向下

<强> slide_down.xml

 <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="200"
        android:fromYDelta="0%p"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toYDelta="100%p" />
</set>

<强> slide_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="200"
        android:fromYDelta="100%p"
        android:toYDelta="0" />
</set>