是否有一种通用的方法来显示大图,并使用户能够放大、缩小和平移图像?
到目前为止,我找到了两种方法:
覆盖ImageView,对于这样一个常见的问题,这似乎有点太多了。 使用webview,但对整体布局的控制较少等等。
是否有一种通用的方法来显示大图,并使用户能够放大、缩小和平移图像?
到目前为止,我找到了两种方法:
覆盖ImageView,对于这样一个常见的问题,这似乎有点太多了。 使用webview,但对整体布局的控制较少等等。
当前回答
This is a very late addition to this thread but I've been working on an image view that supports zoom and pan and has a couple of features I haven't found elsewhere. This started out as a way of displaying very large images without causing OutOfMemoryErrors, by subsampling the image when zoomed out and loading higher resolution tiles when zoomed in. It now supports use in a ViewPager, rotation manually or using EXIF information (90° stops), override of selected touch events using OnClickListener or your own GestureDetector or OnTouchListener, subclassing to add overlays, pan while zooming, and fling momentum.
它不打算作为ImageView的一般使用替代品,因此不扩展它,并且不支持显示来自资源的图像,只支持资产和外部文件。它需要SDK 10。
源代码在GitHub上,有一个示例说明了在ViewPager中的使用。
https://github.com/davemorrissey/subsampling-scale-image-view
其他回答
我刚刚整合了Robert Foss的TouchImageView:它完美地开箱即用!谢谢!
我只是修改了一些代码,所以我可以从我的layout.xml实例化它。
只需添加两个构造函数
public TouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public TouchImageView(Context context) {
super(context);
init(context);
}
并将旧的构造函数转换为init方法:
private void init(Context context){
//...old code ofconstructor of Robert Moss's code
}
更新
我刚刚给TouchImageView一个新的更新。它现在包括双击缩放和抛除平移和捏缩放。下面的代码非常过时。你可以查看github项目以获得最新的代码。
使用
在项目中放置TouchImageView.java。这样就可以像 ImageView。例子:
TouchImageView img = (TouchImageView) findViewById(R.id.img);
如果你在xml中使用TouchImageView,那么你必须提供完整的包 名称,因为它是一个自定义视图。例子:
<com.example.touch.TouchImageView
android:id="@+id/img”
android:layout_width="match_parent"
android:layout_height="match_parent" />
注意:我已经删除了我之前的答案,其中包括一些非常旧的代码,现在直接链接到github上最新的代码。
ViewPager
如果你有兴趣把TouchImageView放在ViewPager中,请参考这个答案。
In Response to Janusz original question, there are several ways to achieve this all of which vary in their difficulty level and have been stated below. Using a web view is good, but it is very limited in terms of look and feel and controllability. If you are drawing a bitmap from a canvas, the most versatile solutions that have been proposed seems to be MikeOrtiz's, Robert Foss's and/or what Jacob Nordfalk suggested. There is a great example for incorporating the android-multitouch-controller by PaulBourke, and is great for having the multi-touch support and alltypes of custom views.
就我个人而言,如果你只是简单地绘制一个画布到一个位图,然后在ImageView中显示它,并希望能够使用多点触摸缩放和移动,我发现MikeOrtiz的解决方案是最简单的。然而,出于我的目的,他提供的Git代码似乎只在他的TouchImageView自定义ImageView类是唯一的子类或提供布局参数时才能工作:
android:layout_height="match_parent"
android:layout_height="match_parent"
不幸的是,由于我的布局设计,我需要“wrap_content”为“layout_height”。当我把它改成这样的时候,图像在底部被裁剪了,我不能滚动或缩放到裁剪的区域。 所以我看了一下ImageView的源代码,看看Android是如何实现“onMeasure”的,并改变MikeOrtiz的以适应。
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//**** ADDED THIS ********/////
int w = (int) bmWidth;
int h = (int) bmHeight;
width = resolveSize(w, widthMeasureSpec);
height = resolveSize(h, heightMeasureSpec);
//**** END ********///
// width = MeasureSpec.getSize(widthMeasureSpec); // REMOVED
// height = MeasureSpec.getSize(heightMeasureSpec); // REMOVED
//Fit to screen.
float scale;
float scaleX = (float)width / (float)bmWidth;
float scaleY = (float)height / (float)bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;
// Center the image
redundantYSpace = (float)height - (scale * (float)bmHeight) ;
redundantXSpace = (float)width - (scale * (float)bmWidth);
redundantYSpace /= (float)2;
redundantXSpace /= (float)2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
// origHeight = bmHeight;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
}
这里的resolveSize(int,int)是一个实用程序,用于将所需的大小与MeasureSpec施加的约束进行协调,其中:
参数:
- size How big the view wants to be
- MeasureSpec Constraints imposed by the parent
返回:
- The size this view should be."
本质上提供了一种行为更类似于图像加载时的原始ImageView类。还可以进行更多的更改,以支持修改纵横比的各种屏幕。但现在我希望这能有所帮助。感谢MikeOrtiz的原始代码,做得很好。
你也可以试试http://code.google.com/p/android-multitouch-controller/
这个图书馆真的很棒,尽管一开始有点难以理解。
如下所示就可以了。
@Override public boolean onTouch(View v,MotionEvent e)
{
tap=tap2=drag=pinch=none;
int mask=e.getActionMasked();
posx=e.getX();posy=e.getY();
float midx= img.getWidth()/2f;
float midy=img.getHeight()/2f;
int fingers=e.getPointerCount();
switch(mask)
{
case MotionEvent.ACTION_POINTER_UP:
tap2=1;break;
case MotionEvent.ACTION_UP:
tap=1;break;
case MotionEvent.ACTION_MOVE:
drag=1;
}
if(fingers==2){nowsp=Math.abs(e.getX(0)-e.getX(1));}
if((fingers==2)&&(drag==0)){ tap2=1;tap=0;drag=0;}
if((fingers==2)&&(drag==1)){ tap2=0;tap=0;drag=0;pinch=1;}
if(pinch==1)
{
if(nowsp>oldsp)scale+=0.1;
if(nowsp<oldsp)scale-=0.1;
tap2=tap=drag=0;
}
if(tap2==1)
{
scale-=0.1;
tap=0;drag=0;
}
if(tap==1)
{
tap2=0;drag=0;
scale+=0.1;
}
if(drag==1)
{
movx=posx-oldx;
movy=posy-oldy;
x+=movx;
y+=movy;
tap=0;tap2=0;
}
m.setTranslate(x,y);
m.postScale(scale,scale,midx,midy);
img.setImageMatrix(m);img.invalidate();
tap=tap2=drag=none;
oldx=posx;oldy=posy;
oldsp=nowsp;
return true;
}
public void onCreate(Bundle b)
{
super.onCreate(b);
img=new ImageView(this);
img.setScaleType(ImageView.ScaleType.MATRIX);
img.setOnTouchListener(this);
path=Environment.getExternalStorageDirectory().getPath();
path=path+"/DCIM"+"/behala.jpg";
byte[] bytes;
bytes=null;
try{
FileInputStream fis;
fis=new FileInputStream(path);
BufferedInputStream bis;
bis=new BufferedInputStream(fis);
bytes=new byte[bis.available()];
bis.read(bytes);
if(bis!=null)bis.close();
if(fis!=null)fis.close();
}
catch(Exception e)
{
ret="Nothing";
}
Bitmap bmp=BitmapFactory.decodeByteArray(bytes,0,bytes.length);
img.setImageBitmap(bmp);
setContentView(img);
}
为查看完整的程序看这里:程序放大图像在android