Android - 使用展开/捏合放大/缩小 RelativeLayout

标签 android android-layout android-animation

我有一个带有 RelativeLayout 的 Activity 和一个私有(private)类,它扩展了 SimpleOnScaleGestureListener。在监听器的 onScale 方法中,我想放大/缩小整个布局(用户看到的所有内容),同时用户展开/捏手指。

我希望布局的更改不是永久性的,即当展开/捏合手势结束时,我希望布局恢复到最初的状态(任何重置都可以在以 SimpleOnScaleGestureListeneronScaleEnd 方法为例)。

我尝试通过在 RelativeLayout 上调用 setScaleXsetScaleY 以及使用 ScaleAnimation。两者都没有导致平滑缩放(或任何可以称为缩放的东西)。甚至可以放大/缩小 RelativeLayout 吗?

我剩下的唯一想法是从缓存中读取屏幕截图并将其作为 ImageView 放在整个布局的顶部,并通过 setImageMatrix 放大/缩小此图像。但是,我不知道如何实现它。

May 布局还包含一个 fragment 容器,该容器在应该可以缩放时是空的。在 onScaleEnd 手势中, fragment 被放入它的容器中(已经实现并且工作正常)。这是我的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_pinch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff" >   


<!-- Layout containing the thumbnail ImageViews -->
<LinearLayout
    android:id="@+id/thumbnail_group_pui"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:orientation="horizontal" >

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/tn_c1"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/tn_c2"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/tn_c3"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/tn_c4"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/tn_c5"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/tn_c6"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/tn_c7"/>

</LinearLayout>


<!-- Layout containing the dashed boxes -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="152dp"
    android:layout_centerVertical="true"
    android:orientation="horizontal" >

    <ImageView
        android:layout_width="177dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:background="@drawable/dashed_box"/>

   <ImageView
        android:layout_width="177dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:background="@drawable/dashed_box"/>

   <ImageView
        android:layout_width="177dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:background="@drawable/dashed_box"/>

   <ImageView
        android:layout_width="177dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:background="@drawable/dashed_box"/>

   <ImageView
        android:layout_width="177dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:background="@drawable/dashed_box"/>

   <ImageView
        android:layout_width="177dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:background="@drawable/dashed_box"/>

   <ImageView
        android:layout_width="177dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:background="@drawable/dashed_box"/>

</LinearLayout>


<!-- Container for the fragments -->
<FrameLayout
    android:id="@+id/fragment_container_pui"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


</RelativeLayout>

编辑 我找到了这两个相关的主题:
Extending RelativeLayout, and overriding dispatchDraw() to create a zoomable ViewGroup
Zoom Content in a RelativeLayout

但是,我没有得到实现。我必须在扩展类中包含哪些其他方法才能实际缩放布局或重置布局?

最佳答案

所以我创建了一个 RelativeLayout 的子类,如上述主题中所述。它看起来像这样:

public class ZoomableRelativeLayout extends RelativeLayout {
float mScaleFactor = 1;
float mPivotX;
float mPivotY;

public ZoomableRelativeLayout(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
}

public ZoomableRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}

public ZoomableRelativeLayout(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
}

protected void dispatchDraw(Canvas canvas) {
    canvas.save(Canvas.MATRIX_SAVE_FLAG);
    canvas.scale(mScaleFactor, mScaleFactor, mPivotX, mPivotY);
    super.dispatchDraw(canvas);
    canvas.restore();
}

public void scale(float scaleFactor, float pivotX, float pivotY) {
    mScaleFactor = scaleFactor;
    mPivotX = pivotX;
    mPivotY = pivotY;
    this.invalidate();
}

public void restore() {
    mScaleFactor = 1;
    this.invalidate();
}

}

我的 SimpleOnScaleGestureListener 实现如下所示:

private class OnPinchListener extends SimpleOnScaleGestureListener {

    float startingSpan; 
    float endSpan;
    float startFocusX;
    float startFocusY;


    public boolean onScaleBegin(ScaleGestureDetector detector) {
        startingSpan = detector.getCurrentSpan();
        startFocusX = detector.getFocusX();
        startFocusY = detector.getFocusY();
        return true;
    }


    public boolean onScale(ScaleGestureDetector detector) {
        mZoomableRelativeLayout.scale(detector.getCurrentSpan()/startingSpan, startFocusX, startFocusY);
        return true;
    }

    public void onScaleEnd(ScaleGestureDetector detector) {
        mZoomableRelativeLayout.restore();
    }
}

希望这会有所帮助!

更新:

您可以使用 ScaleGestureDetector 为您的 ZoomableRelativelayout 集成 OnPinchListener:

ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(this, new OnPinchListener());

并且需要将Zoomable布局的触摸监听器与ScaleGestureDetector的触摸监听器绑定(bind):

mZoomableLayout.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // TODO Auto-generated method stub
                    scaleGestureDetector.onTouchEvent(event);
                    return true;
                }
            });

关于Android - 使用展开/捏合放大/缩小 RelativeLayout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10013906/

相关文章:

java - 从 Android 应用程序对象显示对话框(或需要可用于多个 Activity 的例程)

android - 在 Android 中用两行四个按钮填满整个屏幕

android - 自动完成 TextView 不起作用

Android SDK "Slide"能力

Android fragment 动画onResume

android - 在正在进行的 FragmentTransaction 期间更改 Fragments 的 z 顺序

android - 如何保护我们的应用程序

java - Eclipse Android - Intent 停止工作

android - 如何从 Android 支持库中锁定 CollapsingToolbarLayout

java - 将 GetCheckedRadioButtonId() 与外部单选按钮组一起使用