草庐IT

android - 在 ScrollView 上启用缩放

coder 2023-12-18 原文

我在我的 ScrollView 中放置了某些数据。我想让它放大/缩小。它包含简单的 ImageViewTextView

任何建议都会有所帮助。 谢谢。

这是我的代码:

<ScrollView
    android:id="@+id/viewSoupMenu"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
     android:background="@drawable/soupback" >

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

<LinearLayout
          android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
          android:layout_marginTop="50dp">

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
         android:layout_marginLeft="35dp"
         android:layout_marginTop="30dp"
        android:background="@android:color/transparent"
        android:src="@drawable/flowericon" />

    <ImageButton
        android:id="@+id/btnVegClearSoup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
         android:layout_marginLeft="5dp"
         android:layout_marginTop="20dp"
        android:background="@android:color/transparent"
        android:src="@drawable/btnvegsoupclearclickedxml" />

     </LinearLayout>
</ScrollView>

最佳答案

您可以使用下面提到的类在您的 ImageView 中启用捏合缩放,您可以创建此类的重复类,它扩展 TextView 而不是 ImageView 用于启用缩放。

public class PinchZoomImageView extends ImageView implements OnTouchListener{

    public PinchZoomImageView(Context context) {
        super(context);
        _init();
    }

    public PinchZoomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        _init();
    }

    public PinchZoomImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        _init();
    }

    private void _init(){
        //setOnTouchListener(this);

        view = (ImageView) this;
        view.setOnTouchListener(this);

        metric = new DisplayMetrics();
        // Work around a Cupcake bug

        d_dpi=((0.52f/(metric.densityDpi))*240.0f)-0.52f;
        Log.d("ash","dpi= "+d_dpi);
        if(metric.densityDpi==160)
        d_dpi=0.34f;
        matrix.setTranslate(1f, 1f);
        matrix.setScale((0.52f/800.0f)*metric.widthPixels+d_dpi, (0.52f/480.0f)*metric.heightPixels+d_dpi);
        view.setImageMatrix(matrix);
        bMap =  BitmapFactory.decodeResource(getResources(), R.drawable.mfigure);
        btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(hasFocus){
            init();
        }
    }

    private void init() {
        maxZoom = (3.0f/480.0f)*metric.heightPixels+d_dpi;
        minZoom = (0.52f/800.0f)*metric.widthPixels+d_dpi;
        height = view.getDrawable().getIntrinsicHeight();
        width = view.getDrawable().getIntrinsicWidth();
        viewRect = new RectF(0, 0, view.getWidth(), view.getHeight());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        ImageView view = (ImageView) v;

        // Handle touch events here...
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                savedMatrix.set(matrix);
                start.set(event.getX()/metric.widthPixels * 800, event.getY()/metric.heightPixels * 480);
                Log.d(TAG, "mode=DRAG");
                mode = DRAG;
                click = true;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                Log.d(TAG, "oldDist=" + oldDist);
                if (oldDist > 10f) {
                    savedMatrix.set(matrix);
                    midPoint(mid, event);
                    mode = ZOOM;
                    Log.d(TAG, "mode=ZOOM");
                }
                click = false;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                Log.d(TAG, "mode=NONE");
                if(click)
                    onClick(event.getX(), event.getY(),true);
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {

                    temp_x = ((start.x) - ((event.getX()/metric.widthPixels)*800));
                    temp_y = ((start.y) - ((event.getY()/metric.heightPixels) * 480));               
                    if(FloatMath.sqrt(temp_x * temp_x + temp_y * temp_y)< 10)
                      break;

                    matrix.set(savedMatrix);

                    // limit pan
                    matrix.getValues(matrixValues);
                    float currentY = matrixValues[Matrix.MTRANS_Y];
                    float currentX = matrixValues[Matrix.MTRANS_X];
                    float currentScale = matrixValues[Matrix.MSCALE_X];
                    float currentHeight = height * currentScale;
                    float currentWidth = width * currentScale;
                    float dx = (event.getX()/metric.widthPixels * 800) - start.x;
                    float dy = (event.getY()/metric.heightPixels * 480) - start.y;
                    float newX = currentX+dx;
                    float newY = currentY+dy;

                    RectF drawingRect = new RectF(newX, newY, newX+currentWidth, newY+currentHeight);
                    float diffUp = Math.min(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
                    float diffDown = Math.max(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
                    float diffLeft = Math.min(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
                    float diffRight = Math.max(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
                    if(diffUp > 0 ){
                        dy +=diffUp;
                    }
                    if(diffDown < 0){
                        dy +=diffDown;
                    }
                    if( diffLeft> 0){
                        dx += diffLeft;
                    }
                    if(diffRight < 0){
                        dx += diffRight;
                    }
                    matrix.postTranslate(dx, dy);
                    //selection.set(selection.x + dx, selection.y + dy);
                    click = false;
                }
                else if (mode == ZOOM) {
                    float newDist = spacing(event);
                    Log.d(TAG, "newDist=" + newDist);
                    if (newDist > 10f) {
                        matrix.set(savedMatrix);
                        float scale = newDist / oldDist;

                        matrix.getValues(matrixValues);
                        float currentScale = matrixValues[Matrix.MSCALE_X];

                        // limit zoom
                        if (scale * currentScale > maxZoom) {
                            scale = maxZoom / currentScale;
                        } else if (scale * currentScale < minZoom) {
                            scale = minZoom / currentScale;
                        }
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                }
                break;
        }
        float mv[] = new float[9];
        matrix.getValues(mv);

        Log.d("PV", "Click x " + mv[Matrix.MTRANS_X] + " y " + mv[Matrix.MTRANS_Y] + " cx " + event.getX() + " cy " + event.getY());

        view.setImageMatrix(matrix);
        view.invalidate();
        return true; // indicate event was handled
    }

     public void onClick(float x, float y,boolean state){
        Log.d("TAG","x="+x+" y "+y);
        float mv[] = new float[9];
        matrix.getValues(mv);

        if(btsize != null)
            btsize.recycle();

        btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map);

        if(btSel != null)
            btSel.recycle();

        btSel = BitmapFactory.decodeResource(getResources(), R.drawable.mfigure);

        Canvas canvas;
        try{
            canvas = new Canvas(btsize);
        }
        catch(Exception e){
            btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map).copy(Config.ARGB_8888,true);
            canvas = new Canvas(btsize);
        }

        x -= mv[Matrix.MTRANS_X];
        y -= mv[Matrix.MTRANS_Y];

        float wdt = btsize.getWidth() * mv[Matrix.MSCALE_X];
        float ht = btsize.getHeight() * mv[Matrix.MSCALE_Y];

        float tw = x/wdt;
        float th = y/ht;

        selPoint.set(tw, th);
        if(state)
             canvas.drawBitmap(btSel, (tw * btsize.getWidth()) - (btSel.getWidth()/2), (th * btsize.getHeight()) - (btSel.getHeight()/2), null);
        else
            canvas.drawBitmap(btSel, (x * btsize.getWidth()) - (btSel.getWidth()/2), (y * btsize.getHeight()) - (btSel.getHeight()/2), null);

        setImageBitmap(btsize);

    }

    /** Determine the space between the first two fingers */
    private float spacing(MotionEvent event) {
         float x = ((event.getX(0)/metric.widthPixels)*800) - ((event.getX(1)/metric.widthPixels)*800);
           float y = ((event.getY(0)/metric.heightPixels) * 480) - ((event.getY(1)/metric.heightPixels) * 480);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, MotionEvent event) {
         float x = ((event.getX(0)/metric.widthPixels) * 800) + ((event.getX(1)/metric.widthPixels)*800);
           float y = ((event.getY(0)/metric.heightPixels) * 480) + ((event.getY(1)/metric.heightPixels) * 480);
        point.set(x / 2, y / 2);
    }

    private static final String TAG = "Touch";
    // These matrices will be used to move and zoom image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();

    // We can be in one of these 3 states
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;

    // Remember some things for zooming
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;

    // Limit zoomable/pannable image
    private ImageView view;
    private float[] matrixValues = new float[9];
    private float maxZoom;
    private float minZoom;
    private float height;
    private float width;
    private RectF viewRect;
    private float temp_x,temp_y;
    private boolean click = false;
    public PointF selPoint = new PointF();
    Bitmap bMap;
    private float d_dpi;
    Paint paint = new Paint();
    Canvas canvas = new Canvas();
    private DisplayMetrics metric; 
    Bitmap bt = null;
    Bitmap btsize = null;
    Bitmap btSel = null;

} 

关于android - 在 ScrollView 上启用缩放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18572014/

有关android - 在 ScrollView 上启用缩放的更多相关文章

  1. ruby-on-rails - 启用 Rack::Deflater 时 ETag 发生变化 - 2

    在启用Rack::Deflater来gzip我的响应主体时偶然发现了一些奇怪的东西。也许我遗漏了一些东西,但启用此功能后,响应被压缩,但是资源的ETag在每个请求上都会发生变化。这会强制应用程序每次都响应,而不是发送304。这在没有启用Rack::Deflater的情况下有效,我已经验证页面源没有改变。我正在运行一个使用thin作为Web服务器的Rails应用程序。Gemfile.lockhttps://gist.github.com/2510816有没有什么方法可以让我从Rack中间件获得更多的输出,这样我就可以看到发生了什么?提前致谢。 最佳答案

  2. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  3. ruby - 使用 Selenium WebDriver 启用/禁用 javascript - 2

    出于某种原因,我必须为Firefox禁用javascript(手动,我们按照提到的步骤执行http://support.mozilla.org/en-US/kb/javascript-settings-for-interactive-web-pages#w_enabling-and-disabling-javascript)。使用Ruby的SeleniumWebDriver如何实现这一点? 最佳答案 是的,这是可能的。而是另一种方式。您首先需要查看链接Selenium::WebDriver::Firefox::Profile#[]=

  4. ruby-on-rails - 如何在 Rails 中启用 Ruby 警告? - 2

    我在test.rb中做了这个:defsome_methodp"Firstdefinition"enddefsome_methodp"Seconddefinition"endsome_method当我调用rubytest.rb时,它打印出Seconddefinition(预期)当我调用ruby-wtest.rb时,它会打印Seconddefinition(预期)并打印警告test。rb:5:警告:方法重新定义;丢弃旧的some_method有没有办法在Rails中启用这些警告?(并将警告打印到控制台/日志文件)为什么我要启用警告:例如,如果我无意中重新定义Controller中的一个方法

  5. ruby - 为什么这个启用 SSL 的 Ruby 服务器/客户端测试有效? - 2

    我正在努力在Ruby中创建启用SSL的服务器,以及与服务器一起使用的相应Ruby客户端。为了进行测试,我使用以下命令创建了自己的根CA证书。$:~/devel/ssl-test/ssl/CA$opensslgenrsa-outTestCA.key2048GeneratingRSAprivatekey,2048bitlongmodulus............+++...........................+++eis65537(0x10001)$:~/devel/ssl-test/ssl/CA$opensslreq-new-keyTestCA.key-outTestCA.

  6. Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信) - 2

    运行有问题或需要源码请点赞关注收藏后评论区留言一、利用ContentResolver读写联系人在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。首先要给AndroidMaifest.xml中添加响应的权限配置 下面是往手机通讯录添加联系人信息的例子效果如下分成三个步骤先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱代码 ContactAddActivity类packagecom.example.chapter07;importandroid

  7. Android 10.0 设置默认launcher后安装另外launcher后默认Launcher失效的功能修复 - 2

    1.前言 在10.0的系统rom定制化开发中,在系统中有多个launcher的时候,会在开机进入launcher的时候弹窗launcher列表,让用户选择进入哪个launcher,这样显得特别的不方便所以产品开发中,要求用RoleManager的相关api来设置默认Launcher,但是在设置完默认Launcher以后,在安装一款Launcher的时候,默认Launcher就会失效,在系统设置的默认应用中Launcher选项就为空,点击home键的时候会弹出默认Launcher列表,让选择进入哪个默认Launcher.所以需要从安装Launcher的流程来分析相关的设置。来解决问题设置默认La

  8. ruby-on-rails - 谷歌地图、Ruby on Rails、用一个标记缩放级别 - 2

    我正在使用apneadiving/Google-Maps-for-Rails添加googlemaps支持(感谢awesomegem)但是,我发现了一个小故障,这很可能是我的错。当有多个标记时,auto_zoom效果很好。但是,当只有一个标记时,它会放大到不漂亮的最大级别。“缩放”仅在auto_zoom为false时有效,所以这不是我想要的。因此您可以使用“maxZoom”,但现在用户无法手动放大超出该点,这不是我想要的。有解决办法吗?我的解释有道理吗?这是GoogleMapsAPI的限制吗?谢谢... 最佳答案 此行为是由于goog

  9. AiBote 2022 新研发的自动化框架,支持 Android 和 Windows 系统。速度非常快 - 2

    Ai-Bot基于流行的Node.js和JavaScript语言的一款新自动化框架,支持Windows和Android自动化。1、Windowsxpath元素定位算法支持支持Windows应用、.NET、WPF、Qt、Java和Electron客户端程序和ie、edgechrome浏览器2、Android支持原生APP和H5界面,元素定位速度是appium十倍,无线远程自动化操作多台安卓设备3、基于opencv图色算法,支持找图和多点找色,1080*2340全分辨率找图50MS以内4、内置免费OCR人工智能技术,无限制获取图片文字和找字功能。5、框架协议开源,除官方node.jsSDK外,用户可

  10. Android Gradle 7.1+新版本依赖变化 - 2

    前一段时间由于工作需要把可爱的小雪狐舍弃了,找到了小蜜蜂。但是新版本的小蜜蜂出现了很多和旧版本不一样的位置。1.功能位置迁移,原来在工程build.gradle的buildscript和allprojects移动至setting.gradle并改名为pluginManagement和dependencyResolutionManagement。里面的东西依旧可以按照原来的copy过来。pluginManagement{repositories{gradlePluginPortal()google()mavenCentral()}}dependencyResolutionManagement{r

随机推荐