如何以编程方式将 9 个修补程序的图像重新应用于 ImageView



我有一个在水平滚动视图中定义了 ImageView 的活动。图像源是一个包含 9 个修补程序的文件,该文件被限制为仅拉伸右边缘以填充屏幕。我实现了一个简单的缩放功能,允许用户通过调整位图大小并将新位图分配给视图来双击以放大和缩小。我目前的问题是,当双击以缩小时,当我将新的调整大小的位图分配给视图时,不会应用 9 色块。换句话说,它不是像 9 个补丁文件中定义的那样只拉伸右边缘,而是拉伸整个图像。

这是我的 XML:

<HorizontalScrollView
            android:id="@+id/hScroll"
            android:fillViewport="true"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:fadingEdge="none" >
            <RelativeLayout
                android:id="@+id/rlayoutScrollMap"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" >
                <ImageView
                    android:id="@+id/imgResultMap"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:scaleType="fitXY"
                    android:src="@drawable/map_base"/>
            </RelativeLayout>
        </horizontalScrollView>

这是我代码的相关部分,在 onDoubleTap(( 调用中:

public boolean onDoubleTap(MotionEvent e)  
                {  
                    if (zoom == 1) {
                        zoom = 2; // zoom out
                    } else {
                        zoom = 1; // zoom in
                    }
                    Bitmap image = BitmapFactory.decodeResource(getResources(),R.drawable.map_base);            
                    Bitmap bmp = Bitmap.createScaledBitmap(image, image.getWidth() * zoom, image.getHeight() * zoom, false);
                    ImageView imgResultMap = (ImageView)findViewById(R.id.imgResultMap);
                    imgResultMap.setImageBitmap(bmp);
                    return false; 
                } 

编辑:经过一些研究,我已经弄清楚了。我不仅需要操作位图,还需要包含 9 个修补程序块(它不是位图图像的一部分(,以重新构造新的 9 个修补程序可绘制对象。请参阅下面的示例代码:

    ...
 else {
        // Zoom out
        zoom = 1;
        Bitmap mapBitmapScaled = mapBitmap; 
        // Load the 9-patch data chunk and apply to the view
        byte[] chunk = mapBitmap.getNinePatchChunk();
        NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(), 
            mapBitmapScaled, chunk, new Rect(), null);
        imgResultMap.setImageDrawable(mapNinePatch);
 }
  ....

编辑:经过一些研究,我已经弄清楚了。我不仅需要操作位图,还需要包含 9 个修补程序块(它不是位图图像的一部分(,以重新构造新的 9 个修补程序可绘制对象。请参阅下面的示例代码:

    ...
 else {
        // Zoom out
        zoom = 1;
        Bitmap mapBitmapScaled = mapBitmap; 
        // Load the 9-patch data chunk and apply to the view
        byte[] chunk = mapBitmap.getNinePatchChunk();
        NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(), 
            mapBitmapScaled, chunk, new Rect(), null);
        imgResultMap.setImageDrawable(mapNinePatch);
 }
  ....

编辑#2:对于那些在这里查看我的解决方案的人,还可以查看下面Kai关于内存管理的建议。非常有用的信息。

为什么不只包含两个不同的缩放图像,并在缩放时使用imgResultMap.setImageResource(resId)在它们之间切换?另请注意,您在UIThread中加载和创建位图,这不是提供流畅用户体验的好方法,至少在onCreate((期间仅预加载一次位图并缓存。

移动这个: ImageView imgResultMap = (ImageView)findViewById(R.id.imgResultMap);到在 onCreate 方法中全局初始化。否则,设备必须搜索视图并在每次点击时找到它。

并尝试在从 onDoubleTap 方法返回之前调用imgResultMap.invalidate();(http://developer.android.com/reference/android/view/View.html#invalidate(((

9 补丁图像似乎只有在设置为View的背景图像时才有效。所以:

  • 而不是android:src,在布局 XML 中设置android:background,以及
  • 当您要更改图像时,请拨打setBackgroundResource()

如果你愿意,你也可以使用普通View而不是ImageView;这并不重要。

另一种解决方案是以编程方式将图像设置为ImageResource并设置scaleType

imageView.setImageResource(R.drawable.favorite_driver_icon);
imageView.setScaleType(ScaleType.FIT_XY);

最新更新