如何制作可缩放的滚动视图?

Posted

技术标签:

【中文标题】如何制作可缩放的滚动视图?【英文标题】:How to make zoomable scrollview? 【发布时间】:2013-11-06 02:21:03 【问题描述】:

在我的 android 应用程序中,我需要创建可缩放的活动。我找到了用于缩放线性布局 here 的有用代码。但是在我的应用程序中,一些活动以滚动视图开头,并且此代码无法识别滚动视图。如何为可滚动活动进行捏缩放? 这是我的布局之一。

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scrollViewZoom"
android:layout_
android:layout_
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" >

<LinearLayout
    android:id="@+id/wd_content"
    android:layout_
    android:layout_
    android:layout_marginTop="10dp"
    android:orientation="vertical" >

    <!-- Start Circle -->

    <TableRow
        android:id="@+id/row_circl1"
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:layout_marginTop="30dp"
        android:background="@color/purple_color" >

        <RelativeLayout
            android:id="@+id/circle_layout1"
            android:layout_
            android:layout_
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_engin_circle1"
                android:layout_
                android:layout_
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_engin_bg"
                android:contentDescription="TODO" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/circle_layout2"
            android:layout_
            android:layout_
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_engin_circle2"
                android:layout_
                android:layout_
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_engin_bg"
                android:contentDescription="TODO" />
        </RelativeLayout>
    </TableRow>

    <TableRow
        android:id="@+id/row_name_circle"
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:layout_marginTop="30dp" >

        <RelativeLayout
            android:id="@+id/circle_name_layout1"
            android:layout_
            android:layout_
            android:layout_marginTop="-15dp"
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_name_circle1"
                android:layout_
                android:layout_
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_gauge_name"
                android:contentDescription="TODO" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/circle_name_layout2"
            android:layout_
            android:layout_
            android:layout_marginTop="-15dp"
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_name_circle2"
                android:layout_
                android:layout_
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_gauge_name"
                android:contentDescription="TODO" />
        </RelativeLayout>
    </TableRow>

    <!-- End Circle -->

</LinearLayout>

</ScrollView>

任何想法都会帮助我。 谢谢。

【问题讨论】:

请查看此链接:[enabling-zoom-on-scroll-view][1] 祝你好运。 [1]:***.com/questions/18572014/… 感谢@Adir.el 的回复,但我找到了另一个解决方案。 【参考方案1】:

好的。犁过网后,终于找到了我的答案。 我发现滚动视图的onTouchEvent() 不起作用,所以我必须使用dispatchTouchEvent() 而不是onTouchEvent()。 在顶部,您可以看到我的 xml 代码(在我的问题中),这是我的活动代码,当然还有 cmets。

    // step 1: add some instance
private float mScale = 1f;
private ScaleGestureDetector mScaleDetector;
GestureDetector gestureDetector;

//step 2: create instance from GestureDetector(this step sholude be place into onCreate())
gestureDetector = new GestureDetector(this, new GestureListener());

// animation for scalling
mScaleDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener() 
                                       
        @Override
        public boolean onScale(ScaleGestureDetector detector) 
        
            float scale = 1 - detector.getScaleFactor();

            float prevScale = mScale;
            mScale += scale;

            if (mScale < 0.1f) // Minimum scale condition:
                mScale = 0.1f;

            if (mScale > 10f) // Maximum scale condition:
                mScale = 10f;
            ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1f / prevScale, 1f / mScale, detector.getFocusX(), detector.getFocusY());
            scaleAnimation.setDuration(0);
            scaleAnimation.setFillAfter(true);
            ScrollView layout =(ScrollView) findViewById(R.id.scrollViewZoom);
            layout.startAnimation(scaleAnimation);
            return true;
        
    );


// step 3: override dispatchTouchEvent()
 @Override
 public boolean dispatchTouchEvent(MotionEvent event) 
    super.dispatchTouchEvent(event);
    mScaleDetector.onTouchEvent(event);
    gestureDetector.onTouchEvent(event);
    return gestureDetector.onTouchEvent(event);
 

//step 4: add private class GestureListener

private class GestureListener extends GestureDetector.SimpleOnGestureListener 
    @Override
    public boolean onDown(MotionEvent e) 
        return true;
    
    // event when double tap occurs
    @Override
    public boolean onDoubleTap(MotionEvent e) 
        // double tap fired.
        return true;
    

非常感谢。

【讨论】:

又一命得救!巴西保证再来一杯啤酒! 它只显示捏缩放,我实现时不滚动。 你能解释一下我需要在哪里使用它吗?我创建了一个扩展 Scrollview 的自定义类,并将上面的代码放在该类中。但它给出了初始化异常 无法水平滚动 水平移动的任何解决方案?【参考方案2】:

感谢您的解决方案,我实现它有点不同,因为我的滚动视图位于片段而不是活动中,为了将所有逻辑委托给视图,我建议在同一个自定义滚动视图中添加 dispatchTouchEvent:

package com.your.package;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.animation.ScaleAnimation;
import android.widget.ScrollView;

import com.your.package.R;

public class CustomZoomScrollView extends ScrollView 


    // step 1: add some instance
    private float mScale = 1f;
    private ScaleGestureDetector mScaleDetector;
    GestureDetector gestureDetector;


    public CustomZoomScrollView(Context context) 
        super(context);
    

    public CustomZoomScrollView(Context context, AttributeSet attrs) 
        super(context, attrs);
        //step 2: create instance from GestureDetector(this step should be place into onCreate())
        gestureDetector = new GestureDetector(getContext(), new GestureListener());

        mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener()
        
            @Override
            public boolean onScale(ScaleGestureDetector detector)
            
                float scale = 1 - detector.getScaleFactor();

                float prevScale = mScale;
                mScale += scale;

                if (mScale < 0.1f) // Minimum scale condition:
                    mScale = 0.1f;

                if (mScale > 10f) // Maximum scale condition:
                    mScale = 10f;
                ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1f / prevScale, 1f / mScale, detector.getFocusX(), detector.getFocusY());
                scaleAnimation.setDuration(0);
                scaleAnimation.setFillAfter(true);
                getRootView().findViewById(R.id.svSeats).startAnimation(scaleAnimation);
                return true;
            
        );
    

    // step 3: override dispatchTouchEvent()
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) 
        super.dispatchTouchEvent(event);
        mScaleDetector.onTouchEvent(event);
        gestureDetector.onTouchEvent(event);
        return gestureDetector.onTouchEvent(event);
    

//step 4: add private class GestureListener

    private class GestureListener extends GestureDetector.SimpleOnGestureListener 
        @Override
        public boolean onDown(MotionEvent e) 
            return true;
        
        // event when double tap occurs
        @Override
        public boolean onDoubleTap(MotionEvent e) 
            // double tap fired.
            return true;
        
    

【讨论】:

以上是关于如何制作可缩放的滚动视图?的主要内容,如果未能解决你的问题,请参考以下文章

在两页模式下如何实现可缩放的 UIPageViewController?

如何在可缩放滚动视图中绘制可点击的网格对象,从远程 json 数据中获取数据?

应使用哪些滚动视图和图像视图设置在 iOS 中显示可缩放图片?

在IOS中创建可缩放视图[关闭]

如何使用图像视图制作无限分页滚动视图?

如何使用滚动视图制作可滚动标签?