最近公司要开发一款Android图片浏览器的软件。要求从ZIP文件中读取图片,看了效果,需要滑动翻页,多点缩放,拖动等。但看每个效果在android上实现都不难,但要全部组合在一起实现就比较麻烦,研究了两天,试过viewpager,动手写了几个效果对比,最终还是选择了Gallery来做。但系统自带的Gallery组件不支持对点缩放和拖动【它默认的拖动是翻页,我需要的移动定位图片】,并且当快速滑动时,Gallery是多张连续翻页,而我只需要每次翻页一张。查了Android部分源码。觉得重新Gallery和ImageView来实现。结果还是比较理想的。性能还是不错的,无论是拖动、翻页还是对点缩放都非常流畅。把大致思路放出来共享下,抛砖引玉,如果大家有更好的改进方法,可以共同讨论。



 package com.hongan.test;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.AdapterView;
import android.widget.Gallery;
import android.widget.AdapterView.OnItemSelectedListener;

public class HonagAnGalleryActivity extends Activity implements OnTouchListener {
// 屏幕宽度
public static int screenWidth;
// 屏幕高度
public static int screenHeight;
private MyGallery gallery;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
ZipFileImpl zipFileImpl = new ZipFileImpl();
zipFileImpl.init();
Bitmap bmp = zipFileImpl.initPackage(0);
setContentView(R.layout.main);



gallery = (MyGallery) findViewById(R.id.gallery);
gallery.setVerticalFadingEdgeEnabled(false);// 取消竖直渐变边框
gallery.setHorizontalFadingEdgeEnabled(false);// 取消水平渐变边框
gallery.setAdapter(new GalleryAdapter(this));
// gallery.setOnTouchListener(this);
// gallery.setOnItemSelectedListener(new GalleryChangeListener());
// FrameLayout.LayoutParams params=(FrameLayout.LayoutParams)
// gallery.getLayoutParams();
// params.height=400;
// params.width=300;

screenWidth = getWindow().getWindowManager().getDefaultDisplay().getWidth();
screenHeight = getWindow().getWindowManager().getDefaultDisplay().getHeight();

//
// ZipFileImpl zipFileImpl = new ZipFileImpl();
// zipFileImpl.init();
// Bitmap bmp = zipFileImpl.initPackage(0);

}

float beforeLenght = 0.0f; // 两触点距离
float afterLenght = 0.0f; // 两触点距离
boolean isScale = false;
float currentScale = 1.0f;// 当前图片的缩放比率

private class GalleryChangeListener implements OnItemSelectedListener {

@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
currentScale = 1.0f;
isScale = false;
beforeLenght = 0.0f;
afterLenght = 0.0f;

}

@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub

}

}

@Override
public boolean onTouch(View v, MotionEvent event) {

// Log.i("","touched---------------");
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:// 多点缩放
beforeLenght = spacing(event);
if (beforeLenght > 5f) {
isScale = true;
}
break;
case MotionEvent.ACTION_MOVE:
if (isScale) {
afterLenght = spacing(event);
if (afterLenght < 5f)
break;
float gapLenght = afterLenght - beforeLenght;
if (gapLenght == 0) {
break;
} else if (Math.abs(gapLenght) > 5f) {
// FrameLayout.LayoutParams params =
// (FrameLayout.LayoutParams) gallery.getLayoutParams();
float scaleRate = gapLenght / 854;// 缩放比例
// Log.i("",
// "scaleRate:"+scaleRate+" currentScale:"+currentScale);
// Log.i("", "缩放比例:" +
// scaleRate+" 当前图片的缩放比例:"+currentScale);
// params.height=(int)(800*(scaleRate+1));
// params.width=(int)(480*(scaleRate+1));
// params.height = 400;
// params.width = 300;
// gallery.getChildAt(0).setLayoutParams(new
// Gallery.LayoutParams(300, 300));
Animation myAnimation_Scale = new ScaleAnimation(currentScale, currentScale + scaleRate, currentScale, currentScale + scaleRate, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
// Animation myAnimation_Scale = new
// ScaleAnimation(currentScale, 1+scaleRate, currentScale,
// 1+scaleRate);
myAnimation_Scale.setDuration(100);
myAnimation_Scale.setFillAfter(true);
myAnimation_Scale.setFillEnabled(true);
// gallery.getChildAt(0).startAnimation(myAnimation_Scale);

// gallery.startAnimation(myAnimation_Scale);
currentScale = currentScale + scaleRate;
// gallery.getSelectedView().setLayoutParams(new
// Gallery.LayoutParams((int)(480), (int)(800)));
// Log.i("",
// "===========:::"+gallery.getSelectedView().getLayoutParams().height);
// gallery.getSelectedView().getLayoutParams().height=(int)(800*(currentScale));
// gallery.getSelectedView().getLayoutParams().width=(int)(480*(currentScale));
gallery.getSelectedView().setLayoutParams(new Gallery.LayoutParams((int) (480 * (currentScale)), (int) (854 * (currentScale))));
// gallery.getSelectedView().setLayoutParams(new
// Gallery.LayoutParams((int)(320*(scaleRate+1)),
// (int)(480*(scaleRate+1))));
// gallery.getSelectedView().startAnimation(myAnimation_Scale);
// isScale = false;
beforeLenght = afterLenght;
}
return true;
}
break;
case MotionEvent.ACTION_POINTER_UP:
isScale = false;
break;
}

return false;
}

/**
* 就算两点间的距离
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
}


/**  
 * MyGallery.java
 * @version 1.0
 * @author awp
 * @createTime 2012-5-23 下午03:42:53
 * android.widget.Gallery的子函数。此类很重要。建议仔细看
 */
package com.hongan.test;


import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.widget.Gallery;


public class MyGallery extends Gallery {
private GestureDetector gestureScanner;
private MyImageView imageView;


public MyGallery(Context context) {
super(context);


}


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


public MyGallery(Context context, AttributeSet attrs) {
super(context, attrs);


gestureScanner = new GestureDetector(new MySimpleGesture());
this.setOnTouchListener(new OnTouchListener() {


float baseValue;
float originalScale;


@Override
public boolean onTouch(View v, MotionEvent event) {
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;


if (event.getAction() == MotionEvent.ACTION_DOWN) {
baseValue = 0;
originalScale = imageView.getScale();
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (event.getPointerCount() == 2) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
float value = (float) Math.sqrt(x * x + y * y);// 计算两点的距离
// System.out.println("value:" + value);
if (baseValue == 0) {
baseValue = value;
} else {
float scale = value / baseValue;// 当前两点间的距离除以手指落下时两点间的距离就是需要缩放的比例。
// scale the image
imageView.zoomTo(originalScale * scale, x + event.getX(1), y + event.getY(1));


}
}
}
}
return false;
}


});
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;


float v[] = new float[9];
Matrix m = imageView.getImageMatrix();
m.getValues(v);
// 图片实时的上下左右坐标
float left, right;
// 图片的实时宽,高
float width, height;
width = imageView.getScale() * imageView.getImageWidth();
height = imageView.getScale() * imageView.getImageHeight();
// 一下逻辑为移动图片和滑动gallery换屏的逻辑。如果没对整个框架了解的非常清晰,改动以下的代码前请三思!!!!!!
if ((int) width <= HonagAnGalleryActivity.screenWidth && (int) height <= HonagAnGalleryActivity.screenHeight)// 如果图片当前大小<屏幕大小,直接处理滑屏事件
{
super.onScroll(e1, e2, distanceX, distanceY);
} else {
left = v[Matrix.MTRANS_X];
right = left + width;
Rect r = new Rect();
imageView.getGlobalVisibleRect(r);


if (distanceX > 0)// 向左滑动
{
if (r.left > 0) {// 判断当前ImageView是否显示完全
super.onScroll(e1, e2, distanceX, distanceY);
} else if (right < HonagAnGalleryActivity.screenWidth) {
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
} else if (distanceX < 0)// 向右滑动
{
if (r.right < HonagAnGalleryActivity.screenWidth) {
super.onScroll(e1, e2, distanceX, distanceY);
} else if (left > 0) {
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
}


}


} else {
super.onScroll(e1, e2, distanceX, distanceY);
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}


@Override
public boolean onTouchEvent(MotionEvent event) {
gestureScanner.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 判断上下边界是否越界
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;
float width = imageView.getScale() * imageView.getImageWidth();
float height = imageView.getScale() * imageView.getImageHeight();
if ((int) width <= HonagAnGalleryActivity.screenWidth && (int) height <= HonagAnGalleryActivity.screenHeight)// 如果图片当前大小<屏幕大小,判断边界
{
break;
}
float v[] = new float[9];
Matrix m = imageView.getImageMatrix();
m.getValues(v);
float top = v[Matrix.MTRANS_Y];
float bottom = top + height;
if (top > 0) {
imageView.postTranslateDur(-top, 200f);
}
Log.i("manga", "bottom:" + bottom);
if (bottom < HonagAnGalleryActivity.screenHeight) {
imageView.postTranslateDur(HonagAnGalleryActivity.screenHeight - bottom, 200f);
}


}
break;
}
return super.onTouchEvent(event);
}


private class MySimpleGesture extends SimpleOnGestureListener {
// 按两下的第二下Touch down时触发
public boolean onDoubleTap(MotionEvent e) {
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;
if (imageView.getScale() > imageView.getScaleRate()) {
imageView.zoomTo(imageView.getScaleRate(), HonagAnGalleryActivity.screenWidth / 2, HonagAnGalleryActivity.screenHeight / 2, 200f);
// imageView.layoutToCenter();
} else {
imageView.zoomTo(1.0f, HonagAnGalleryActivity.screenWidth / 2, HonagAnGalleryActivity.screenHeight / 2, 200f);
}


} else {


}
// return super.onDoubleTap(e);
return true;
}
}
}

/**  
 * MyImageView.java
 * @version 1.0
 * @author awp
 * @createTime 2012-5-23 下午03:12:30
 * 此类代码是根据android系统自带的ImageViewTouchBase代码修改
 */
package com.hongan.test;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.ImageView;


public class MyImageView extends ImageView {
@SuppressWarnings("unused")
private static final String TAG = "ImageViewTouchBase";


// This is the base transformation which is used to show the image
// initially. The current computation for this shows the image in
// it's entirety, letterboxing as needed. One could choose to
// show the image as cropped instead.
//
// This matrix is recomputed when we go from the thumbnail image to
// the full size image.
protected Matrix mBaseMatrix = new Matrix();


// This is the supplementary transformation which reflects what
// the user has done in terms of zooming and panning.
//
// This matrix reHonagAnGalleryActivitys the same when we go from the thumbnail image
// to the full size image.
protected Matrix mSuppMatrix = new Matrix();


// This is the final matrix which is computed as the concatentation
// of the base matrix and the supplementary matrix.
private final Matrix mDisplayMatrix = new Matrix();


// Temporary buffer used for getting the values out of a matrix.
private final float[] mMatrixValues = new float[9];


// The current bitmap being displayed.
// protected final RotateBitmap mBitmapDisplayed = new RotateBitmap(null);
protected Bitmap image = null;


int mThisWidth = -1, mThisHeight = -1;


float mMaxZoom = 2.0f;// 最大缩放比例
float mMinZoom ;// 最小缩放比例


private int imageWidth;// 图片的原始宽度
private int imageHeight;// 图片的原始高度


private float scaleRate;// 图片适应屏幕的缩放比例


public MyImageView(Context context, int imageWidth, int imageHeight) {
super(context);
this.imageHeight = imageHeight;
this.imageWidth = imageWidth;
init();
}


public MyImageView(Context context, AttributeSet attrs, int imageWidth, int imageHeight) {
super(context, attrs);
this.imageHeight = imageHeight;
this.imageWidth = imageWidth;
init();
}


/**
 * 计算图片要适应屏幕需要缩放的比例
 */
private void arithScaleRate() {
float scaleWidth = HonagAnGalleryActivity.screenWidth / (float) imageWidth;
float scaleHeight = HonagAnGalleryActivity.screenHeight / (float) imageHeight;
scaleRate = Math.min(scaleWidth, scaleHeight);
}


public float getScaleRate() {
return scaleRate;
}


public int getImageWidth() {
return imageWidth;
}


public void setImageWidth(int imageWidth) {
this.imageWidth = imageWidth;
}


public int getImageHeight() {
return imageHeight;
}


public void setImageHeight(int imageHeight) {
this.imageHeight = imageHeight;
}


@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
event.startTracking();
return true;
}
return super.onKeyDown(keyCode, event);
}


@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking() && !event.isCanceled()) {
if (getScale() > 1.0f) {
// If we're zoomed in, pressing Back jumps out to show the
// entire image, otherwise Back returns the user to the gallery.
zoomTo(1.0f);
return true;
}
}
return super.onKeyUp(keyCode, event);
}


protected Handler mHandler = new Handler();


@Override
public void setImageBitmap(Bitmap bitmap) {
super.setImageBitmap(bitmap);
image = bitmap;
// 计算适应屏幕的比例
arithScaleRate();
//缩放到屏幕大小
zoomTo(scaleRate,HonagAnGalleryActivity.screenWidth / 2f, HonagAnGalleryActivity.screenHeight / 2f);

//居中
layoutToCenter();

// imageView.zoomTo(scaleRate, HonagAnGalleryActivity.screenWidth / 2, HonagAnGalleryActivity.screenHeight / 2
// center(true, true);
}


// Center as much as possible in one or both axis. Centering is
// defined as follows: if the image is scaled down below the
// view's dimensions then center it (literally). If the image
// is scaled larger than the view and is translated out of view
// then translate it back into view (i.e. eliminate black bars).
protected void center(boolean horizontal, boolean vertical) {
// if (mBitmapDisplayed.getBitmap() == null) {
// return;
// }
if (image == null) {
return;
}


Matrix m = getImageViewMatrix();


RectF rect = new RectF(0, 0, image.getWidth(), image.getHeight());
// RectF rect = new RectF(0, 0, imageWidth*getScale(), imageHeight*getScale());


m.mapRect(rect);


float height = rect.height();
float width = rect.width();


float deltaX = 0, deltaY = 0;


if (vertical) {
int viewHeight = getHeight();
if (height < viewHeight) {
deltaY = (viewHeight - height) / 2 - rect.top;
} else if (rect.top > 0) {
deltaY = -rect.top;
} else if (rect.bottom < viewHeight) {
deltaY = getHeight() - rect.bottom;
}
}


if (horizontal) {
int viewWidth = getWidth();
if (width < viewWidth) {
deltaX = (viewWidth - width) / 2 - rect.left;
} else if (rect.left > 0) {
deltaX = -rect.left;
} else if (rect.right < viewWidth) {
deltaX = viewWidth - rect.right;
}
}


postTranslate(deltaX, deltaY);
setImageMatrix(getImageViewMatrix());
}


private void init() {
setScaleType(ImageView.ScaleType.MATRIX);
}

/**
 * 设置图片居中显示
 */
public void layoutToCenter()
{
//正在显示的图片实际宽高
float width = imageWidth*getScale();
float height = imageHeight*getScale();

//空白区域宽高
float fill_width = HonagAnGalleryActivity.screenWidth - width;
float fill_height = HonagAnGalleryActivity.screenHeight - height;

//需要移动的距离
float tran_width = 0f;
float tran_height = 0f;

if(fill_width>0)
tran_width = fill_width/2;
if(fill_height>0)
tran_height = fill_height/2;


postTranslate(tran_width, tran_height);
setImageMatrix(getImageViewMatrix());
}


protected float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
mMinZoom =( HonagAnGalleryActivity.screenWidth/2f)/imageWidth;

return mMatrixValues[whichValue];
}


// Get the scale factor out of the matrix.
protected float getScale(Matrix matrix) {
return getValue(matrix, Matrix.MSCALE_X);
}


protected float getScale() {
return getScale(mSuppMatrix);
}


// Combine the base matrix and the supp matrix to make the final matrix.
protected Matrix getImageViewMatrix() {
// The final matrix is computed as the concatentation of the base matrix
// and the supplementary matrix.
mDisplayMatrix.set(mBaseMatrix);
mDisplayMatrix.postConcat(mSuppMatrix);
return mDisplayMatrix;
}


static final float SCALE_RATE = 1.25F;


// Sets the maximum zoom, which is a scale relative to the base matrix. It
// is calculated to show the image at 400% zoom regardless of screen or
// image orientation. If in the future we decode the full 3 megapixel image,
// rather than the current 1024x768, this should be changed down to 200%.
protected float maxZoom() {
if (image == null) {
return 1F;
}


float fw = (float) image.getWidth() / (float) mThisWidth;
float fh = (float) image.getHeight() / (float) mThisHeight;
float max = Math.max(fw, fh) * 4;
return max;
}


protected void zoomTo(float scale, float centerX, float centerY) {
if (scale > mMaxZoom) {
scale = mMaxZoom;
} else if (scale < mMinZoom) {
scale = mMinZoom;
}


float oldScale = getScale();
float deltaScale = scale / oldScale;


mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY);
setImageMatrix(getImageViewMatrix());
center(true, true);
}


protected void zoomTo(final float scale, final float centerX, final float centerY, final float durationMs) {
final float incrementPerMs = (scale - getScale()) / durationMs;
final float oldScale = getScale();
final long startTime = System.currentTimeMillis();


mHandler.post(new Runnable() {
public void run() {
long now = System.currentTimeMillis();
float currentMs = Math.min(durationMs, now - startTime);
float target = oldScale + (incrementPerMs * currentMs);
zoomTo(target, centerX, centerY);
if (currentMs < durationMs) {
mHandler.post(this);
}
}
});
}



protected void zoomTo(float scale) {
float cx = getWidth() / 2F;
float cy = getHeight() / 2F;


zoomTo(scale, cx, cy);
}


protected void zoomToPoint(float scale, float pointX, float pointY) {
float cx = getWidth() / 2F;
float cy = getHeight() / 2F;


panBy(cx - pointX, cy - pointY);
zoomTo(scale, cx, cy);
}


protected void zoomIn() {
zoomIn(SCALE_RATE);
}


protected void zoomOut() {
zoomOut(SCALE_RATE);
}


protected void zoomIn(float rate) {
if (getScale() >= mMaxZoom) {
return; // Don't let the user zoom into the molecular level.
} else if (getScale() <= mMinZoom) {
return;
}
if (image == null) {
return;
}


float cx = getWidth() / 2F;
float cy = getHeight() / 2F;


mSuppMatrix.postScale(rate, rate, cx, cy);
setImageMatrix(getImageViewMatrix());
}


protected void zoomOut(float rate) {
if (image == null) {
return;
}


float cx = getWidth() / 2F;
float cy = getHeight() / 2F;


// Zoom out to at most 1x.
Matrix tmp = new Matrix(mSuppMatrix);
tmp.postScale(1F / rate, 1F / rate, cx, cy);


if (getScale(tmp) < 1F) {
mSuppMatrix.setScale(1F, 1F, cx, cy);
} else {
mSuppMatrix.postScale(1F / rate, 1F / rate, cx, cy);
}
setImageMatrix(getImageViewMatrix());
center(true, true);
}


public void postTranslate(float dx, float dy) {
mSuppMatrix.postTranslate(dx, dy);
setImageMatrix(getImageViewMatrix());
}
float _dy=0.0f;
protected void postTranslateDur( final float dy, final float durationMs) {
_dy=0.0f;
final float incrementPerMs = dy / durationMs;
final long startTime = System.currentTimeMillis();
mHandler.post(new Runnable() {
public void run() {
long now = System.currentTimeMillis();
float currentMs = Math.min(durationMs, now - startTime);

postTranslate(0, incrementPerMs*currentMs-_dy);
_dy=incrementPerMs*currentMs;


if (currentMs < durationMs) {
mHandler.post(this);
}
}
});
}


protected void panBy(float dx, float dy) {
postTranslate(dx, dy);
setImageMatrix(getImageViewMatrix());
}
}

package com.hongan.test;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;


import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;


public class ZipFileImpl 
{
public  static int zipFileSize;



public static final String PACKAGE_TYPE_ZIP = "ZIP"; // zip包
    public static final String PACKAGE_TYPE_MCP = "MCP"; // 专用包
    public static final int PAGE_AREA_SIZE=40;            //翻页区域
    private ArrayList zipfileList = null; // zip包中的文件列表
    private ZipFile zipFile = null; // 漫画包文件
    private int playIndex = 0; // 正在播放中的图片。
    private Bitmap playBitmap = null; // 正在播放中的图片
    private String cartoonPackagePath = "mnt/sdcard/file/file1.zip/"; // 图片包的路径(一般为sdcard/cmsreader/cartoon/中位置)
    private String packageType = ""; // 图片包类型
    /**
     * 初始化图片包。
     */
    
    public void init()
    {
    
      setCartoonPackagePath(cartoonPackagePath);;
    }
    public Bitmap initPackage(int position) {
        if (getPackageType().equals(PACKAGE_TYPE_MCP)) {
            // 如果是mcp格式的文件,则转移为zip格式直接读取
        } else if (getPackageType().equals(PACKAGE_TYPE_ZIP)) {
            // 如果是zip文件格式,则直接生成
            try {
             Log.i("awp", "cartoonPackagePath is "+ cartoonPackagePath);
                zipFile = new ZipFile(cartoonPackagePath);
                Log.i("awp", "zipFile is "+ zipFile.getName());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Enumeration en=(Enumeration) zipFile.entries();
       // Enumeration e = (Enumeration) zipFile.entries(); // 获取zip文件中的目录及文件列表
        ZipEntry entry = null;
        zipfileList = new ArrayList();
        while (en.hasMoreElements()) {
            entry = en.nextElement();
            if (!entry.isDirectory()) {
                // 如果文件不是目录,则添加到列表中
                zipfileList.add(entry);
            }
        }
        Log.i("awp","pic is "+ zipfileList.size());
        zipFileSize=zipfileList.size();
     
        // 初始化当前播放图片
        playBitmap = createBitmap(position);
        return playBitmap;
    }


    /**
     * 获得图片包路径。
     * 
     * @return
     */
    public String getCartoonPackagePath() {
        return cartoonPackagePath;
    }


    /**
     * 设置图片包路径。
     * 
     * @param cartoonPackagePath
     */
    public void setCartoonPackagePath(String cartoonPackagePath) {
        this.cartoonPackagePath = cartoonPackagePath;
        // 设置类型
        if (cartoonPackagePath.endsWith(".mcp")) {
            setPackageType(PACKAGE_TYPE_MCP);
        } else {
            setPackageType(PACKAGE_TYPE_ZIP);
        }
        
    }


    /**
     * 获取图片包格式。
     * 
     * @return
     */
    public String getPackageType() {
        return packageType;
    }


    /**
     * 设置图片包格式。
     * 
     * @param packageType
     */
    private void setPackageType(String packageType) {
        this.packageType = packageType;
    }


    /**
     * 根据图片编号创建一张图片,编号从0开始。
     * 
     * @param pictureid
     * @return
     */
    private Bitmap createBitmap(int pictureid) {
//        System.out.println("CreateBitmapBegin");
        Bitmap result = null;
        try {
            result = new BitmapDrawable(zipFile.getInputStream(zipfileList
                    .get(pictureid))).getBitmap();
        } catch (IOException e) {
            e.printStackTrace();
        }
//        System.out.println("CreateBitmapEnd");
        return result;
    }
}

/**  
 * MyGallery.java
 * @version 1.0
 * @author awp
 * @createTime 2012-5-23下午03:42:53
 * android.widget.Gallery的子函数。此类很重要。建议仔细看
 */
package com.hongan.test;


import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.widget.Gallery;


public class MyGallery extends Gallery {
private GestureDetector gestureScanner;
private MyImageView imageView;


public MyGallery(Context context) {
super(context);


}


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


public MyGallery(Context context, AttributeSet attrs) {
super(context, attrs);


gestureScanner = new GestureDetector(new MySimpleGesture());
this.setOnTouchListener(new OnTouchListener() {


float baseValue;
float originalScale;


@Override
public boolean onTouch(View v, MotionEvent event) {
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;


if (event.getAction() == MotionEvent.ACTION_DOWN) {
baseValue = 0;
originalScale = imageView.getScale();
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (event.getPointerCount() == 2) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
float value = (float) Math.sqrt(x * x + y * y);// 计算两点的距离
// System.out.println("value:" + value);
if (baseValue == 0) {
baseValue = value;
} else {
float scale = value / baseValue;// 当前两点间的距离除以手指落下时两点间的距离就是需要缩放的比例。
// scale the image
imageView.zoomTo(originalScale * scale, x + event.getX(1), y + event.getY(1));


}
}
}
}
return false;
}


});
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;


float v[] = new float[9];
Matrix m = imageView.getImageMatrix();
m.getValues(v);
// 图片实时的上下左右坐标
float left, right;
// 图片的实时宽,高
float width, height;
width = imageView.getScale() * imageView.getImageWidth();
height = imageView.getScale() * imageView.getImageHeight();
// 一下逻辑为移动图片和滑动gallery换屏的逻辑。如果没对整个框架了解的非常清晰,改动以下的代码前请三思!!!!!!
if ((int) width <= HonagAnGalleryActivity.screenWidth && (int) height <= HonagAnGalleryActivity.screenHeight)// 如果图片当前大小<屏幕大小,直接处理滑屏事件
{
super.onScroll(e1, e2, distanceX, distanceY);
} else {
left = v[Matrix.MTRANS_X];
right = left + width;
Rect r = new Rect();
imageView.getGlobalVisibleRect(r);


if (distanceX > 0)// 向左滑动
{
if (r.left > 0) {// 判断当前ImageView是否显示完全
super.onScroll(e1, e2, distanceX, distanceY);
} else if (right < HonagAnGalleryActivity.screenWidth) {
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
} else if (distanceX < 0)// 向右滑动
{
if (r.right < HonagAnGalleryActivity.screenWidth) {
super.onScroll(e1, e2, distanceX, distanceY);
} else if (left > 0) {
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
}


}


} else {
super.onScroll(e1, e2, distanceX, distanceY);
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}


@Override
public boolean onTouchEvent(MotionEvent event) {
gestureScanner.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 判断上下边界是否越界
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;
float width = imageView.getScale() * imageView.getImageWidth();
float height = imageView.getScale() * imageView.getImageHeight();
if ((int) width <= HonagAnGalleryActivity.screenWidth && (int) height <= HonagAnGalleryActivity.screenHeight)// 如果图片当前大小<屏幕大小,判断边界
{
break;
}
float v[] = new float[9];
Matrix m = imageView.getImageMatrix();
m.getValues(v);
float top = v[Matrix.MTRANS_Y];
float bottom = top + height;
if (top > 0) {
imageView.postTranslateDur(-top, 200f);
}
Log.i("manga", "bottom:" + bottom);
if (bottom < HonagAnGalleryActivity.screenHeight) {
imageView.postTranslateDur(HonagAnGalleryActivity.screenHeight - bottom, 200f);
}


}
break;
}
return super.onTouchEvent(event);
}


private class MySimpleGesture extends SimpleOnGestureListener {
// 按两下的第二下Touch down时触发
public boolean onDoubleTap(MotionEvent e) {
View view = MyGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) view;
if (imageView.getScale() > imageView.getScaleRate()) {
imageView.zoomTo(imageView.getScaleRate(), HonagAnGalleryActivity.screenWidth / 2, HonagAnGalleryActivity.screenHeight / 2, 200f);
// imageView.layoutToCenter();
} else {
imageView.zoomTo(1.0f, HonagAnGalleryActivity.screenWidth / 2, HonagAnGalleryActivity.screenHeight / 2, 200f);
}


} else {


}
// return super.onDoubleTap(e);
return true;
}
}
}


因为 大家对Gallery都很了解,这里就不在多做解释了,不了解的童鞋可以看注释。

更多相关文章

  1. Android学习07-----事件处理(1)单击事件_改变屏幕方向和密码明文
  2. Android(安卓).9.png图片的制作与使用
  3. Icon Design Guidelines-android 图标设计指导
  4. Android(安卓)PowerImageView实现,可以播放动画的强大ImageView
  5. Android(安卓)屏幕适配(修改系统字体大小、显示大小、修改分辨率
  6. Android共享动画兼容实现
  7. Android(安卓)判断imageview角度并旋转
  8. Android中自定义drawable states
  9. android实现点击按钮控制图片切换

随机推荐

  1. fragment嵌套使用时getFragmentManager.f
  2. 关于android:id="@+id/xx"的理解
  3. 使用Android系统调用裁剪图片并保存
  4. android sdk manager 无法更新
  5. AAPT2 error: check logs for details.
  6. Android新姿势:截屏代码整理
  7. android系统启动流程启动画面学习之init
  8. Android 通过Jni调用Native
  9. Android中有关Handler的总结
  10. Android(安卓)系列的光照效果