デフォルトのAndroid Galleryに似たView Pagerで、Imageviewにピンチズームを実装したい。GitHubで複数のソースを見つけたが、ズームとスライドは最初の画像に対してのみ機能する。
私が試したもの:
1.) TouchImageView
2.) PhotoView
上記のリンクはすべて、単一の画像ビューで正常に機能します。しかし、View pagerの画像に関しては、いくつかの不具合があり、View Pagerの最初の画像でのみ正常に機能します。ビューページャーで3番目から4番目の画像にスクロールすると、画像がズームされている場合、ドラッグ機能が期待どおりに機能しません。
誰かがこれを行うための良いライブラリを知っているなら、それらへのリンクを私に提供してください。
編集2:サンプルコードはTouchImageViewのマスターブランチにプッシュされています。 例のアクティビティへのリンク および ExtendedViewPagerへのリンク です。
編集:TouchImageViewへのサンプルリンクを適応させるコードを追加しました。注:現在devブランチにある最新のコードが必要になります。将来、これはv1.2.0に含まれる予定です。 TouchImageViewがcanScrollHorizontallyをオーバーライドする場合、最新のコードがあることがわかります。
ステップ1:ViewPagerを拡張し、canScrollをオーバーライドしてcanScrollHorizontallyFroyoを呼び出します。
public class ExtendedViewPager extends ViewPager {
public ExtendedViewPager(Context context) {
super(context);
}
public ExtendedViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof TouchImageView) {
return ((TouchImageView) v).canScrollHorizontallyFroyo(-dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
}
ステップ2:canScrollHorizontallyFroyoを追加してTouchImageViewを変更します。
public boolean canScrollHorizontallyFroyo(int direction) {
return canScrollHorizontally(direction);
}
ステップ3:あなたの活動
public class TouchImageViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ExtendedViewPager mViewPager = (ExtendedViewPager) findViewById(R.id.view_pager);
setContentView(mViewPager);
mViewPager.setAdapter(new TouchImageAdapter());
}
static class TouchImageAdapter extends PagerAdapter {
private static int[] images = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };
@Override
public int getCount() {
return images.length;
}
@Override
public View instantiateItem(ViewGroup container, int position) {
TouchImageView img = new TouchImageView(container.getContext());
img.setImageResource(images[position]);
container.addView(img, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
return img;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}
ステップ4:main.xml
<com.example.touch.ExtendedViewPager
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/view_pager"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
TouchImageViewは実際には私のプロジェクトです。現在、 修正 が devブランチ にあり、今後のリリースでマスターにプッシュされるViewPagersと統合します。残念ながら、ハニカムおよびそれ以前ではcanScrollHorizontally
を呼び出さないため、この修正はAPI 14以降にのみ適用されます。古いAPIをサポートする必要がある場合は、ViewPagerに回避策を実装する必要があります。 ここに例があります。
ImageViewZoom ライブラリを使用して、かなりの解決策を見つけました。 ViewPagerでズームされた画像をスクロールするために、独自のViewPagerを作成しました。
public class ExtendedViewPager extends ViewPager {
public ExtendedViewPager(Context context) {
super(context);
}
public ExtendedViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ImageViewTouch) {
return ((ImageViewTouch) v).canScroll(dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
}
上記のソリューションを数時間テストした後、ようやく素晴らしい Subsampling Scale Image View ライブラリが見つかりました。これはAndroid Support Package。
ImageViewZoom Library を使用した私のソリューションは、このカスタムViewPagerに基づいています。
public class ImageViewTouchViewPager extends ViewPager {
public ImageViewTouchViewPager(Context context) {
super(context);
}
public ImageViewTouchViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ImageViewTouch) {
ImageViewTouch imageViewTouch = (ImageViewTouch)v;
if (imageViewTouch.getScale() == imageViewTouch.getMinScale()) {
return super.canScroll(v, checkV, dx, x, y);
}
return imageViewTouchCanScroll(imageViewTouch, dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
/**
* Determines whether the ImageViewTouch can be scrolled.
*
* @param direction - positive direction value means scroll from right to left,
* negative value means scroll from left to right
* @return true if there is some more place to scroll, false - otherwise.
*/
private boolean imageViewTouchCanScroll(ImageViewTouch v, int direction){
RectF bitmapRect = v.getBitmapRect();
Rect imageViewRect = new Rect();
getGlobalVisibleRect(imageViewRect);
if (null == bitmapRect) {
return false;
}
if (direction < 0) {
return Math.abs(bitmapRect.right - imageViewRect.right) > 1.0f;
}else {
return Math.abs(bitmapRect.left - imageViewRect.left) > 1.0f;
}
}
}
以前のソリューションを修正しました。 ImageViewTouchがモードズームの場合、ページをスクロールできます。
public class ImageViewTouchViewPager extends ViewPager {
public ImageViewTouchViewPager(Context context) {
super(context);
}
public ImageViewTouchViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ImageViewTouch) {
ImageViewTouch imageViewTouch = (ImageViewTouch)v;
return imageViewTouchCanScroll(imageViewTouch, dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
/**
* Determines whether the ImageViewTouch can be scrolled.
*
* @param direction - positive direction value means scroll from right to left,
* negative value means scroll from left to right
* @return true if there is some more place to scroll, false - otherwise.
*/
private boolean imageViewTouchCanScroll(ImageViewTouch imageViewTouch, int direction){
int widthScreen = getWidthScreen();
RectF bitmapRect = imageViewTouch.getBitmapRect();
Rect imageViewRect = new Rect();
getGlobalVisibleRect(imageViewRect);
int widthBitmapViewTouch = (int)bitmapRect.width();
if (null == bitmapRect) {
return false;
}
if(widthBitmapViewTouch < widthScreen){
return false;
}
if (direction < 0) {
return Math.abs(bitmapRect.right - imageViewRect.right) > 1.0f;
}else {
return Math.abs(bitmapRect.left - imageViewRect.left) > 1.0f;
}
}
private int getWidthScreen(){
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size.x;
}
}