首页 > 编程技术 > android

Android开发之游戏引擎AndEngine资料简单介绍

发布时间:2016-9-20 20:00

最近查看了一些关于开源Android游戏引擎的资料,觉得AndEngine功能强大,例子丰富,更新较快。由于初学,找资料化不少时间,现在将自己在网上收集的比较实用的资料网址贴在这里,大家一起学习和讨论。


1.AndEngine源码和例子代码地址:

Google Code:http://code.google.com/p/andengine/

AndEngine主页:http://www.andengine.org/

example地址:http://code.google.com/p/andengineexamples/

 

2.代码下载

先安装TortoiseHg,然后在想要存放代码的目录右键-->TortoiseHg-->clone

hg clone https://andengine.googlecode.com/hg/andengine

 

3.lib包下载

andengineexamples->Source->Browse->hg->lib(libs->armeabi)->点击想下载的Filename->View raw file

 

4.入门文章

中文 http://blog.111cn.net/cping1982/archive/2011/03/06/6227775.aspx

英文 http://www.andengine.org/forums/ ... rial-list-t417.html

 

虽然听说AndEngine在某些型号的机型上有不稳定的情况出现,但决定学习这个引擎是因为它内置了BOX2D物理引擎,在手机上测试运行也比较流畅,效果很给力~~~希望大家喜欢

本文章介绍了关于android开发之zip文件压缩解压缩 ,有需要学习android手机开发时文件操作的朋友可以参考一下。
 代码如下 复制代码

//----------------- DirTraversal.java
package com.once;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
/**
* 文件夹遍历
* @author once
*
*/
public class DirTraversal {

//no recursion
public static LinkedList<File> listLinkedFiles(String strPath) {
LinkedList<File> list = new LinkedList<File>();
File dir = new File(strPath);
File file[] = dir.listFiles();
for (int i = 0; i < file.length; i++) {
if (file[i].isDirectory())
list.add(file[i]);
else
System.out.println(file[i].getAbsolutePath());
}
File tmp;
while (!list.isEmpty()) {
tmp = (File) list.removeFirst();
if (tmp.isDirectory()) {
file = tmp.listFiles();
if (file == null)
continue;
for (int i = 0; i < file.length; i++) {
if (file[i].isDirectory())
list.add(file[i]);
else
System.out.println(file[i].getAbsolutePath());
}
} else {
System.out.println(tmp.getAbsolutePath());
}
}
return list;
}


//recursion
public static ArrayList<File> listFiles(String strPath) {
return refreshFileList(strPath);
}

public static ArrayList<File> refreshFileList(String strPath) {
ArrayList<File> filelist = new ArrayList<File>();
File dir = new File(strPath);
File[] files = dir.listFiles();

if (files == null)
return null;
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
refreshFileList(files[i].getAbsolutePath());
} else {
if(files[i].getName().toLowerCase().endsWith("zip"))
filelist.add(files[i]);
}
}
return filelist;
}
}

//----------------- ZipUtils.java
package com.once;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
* Java utils 实现的Zip工具
*
* @author once
*/
public class ZipUtils {
private static final int BUFF_SIZE = 1024 * 1024; // 1M Byte

/**
* 批量压缩文件(夹)
*
* @param resFileList 要压缩的文件(夹)列表
* @param zipFile 生成的压缩文件
* @throws IOException 当压缩过程出错时抛出
*/
public static void zipFiles(Collection<File> resFileList, File zipFile) throws IOException {
ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(
zipFile), BUFF_SIZE));
for (File resFile : resFileList) {
zipFile(resFile, zipout, "");
}
zipout.close();
}

/**
* 批量压缩文件(夹)
*
* @param resFileList 要压缩的文件(夹)列表
* @param zipFile 生成的压缩文件
* @param comment 压缩文件的注释
* @throws IOException 当压缩过程出错时抛出
*/
public static void zipFiles(Collection<File> resFileList, File zipFile, String comment)
throws IOException {
ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(
zipFile), BUFF_SIZE));
for (File resFile : resFileList) {
zipFile(resFile, zipout, "");
}
zipout.setComment(comment);
zipout.close();
}

/**
* 解压缩一个文件
*
* @param zipFile 压缩文件
* @param folderPath 解压缩的目标目录
* @throws IOException 当解压缩过程出错时抛出
*/
public static void upZipFile(File zipFile, String folderPath) throws ZipException, IOException {
File desDir = new File(folderPath);
if (!desDir.exists()) {
desDir.mkdirs();
}
ZipFile zf = new ZipFile(zipFile);
for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();) {
ZipEntry entry = ((ZipEntry)entries.nextElement());
InputStream in = zf.getInputStream(entry);
String str = folderPath + File.separator + entry.getName();
str = new String(str.getBytes("8859_1"), "GB2312");
File desFile = new File(str);
if (!desFile.exists()) {
File fileParentDir = desFile.getParentFile();
if (!fileParentDir.exists()) {
fileParentDir.mkdirs();
}
desFile.createNewFile();
}
OutputStream out = new FileOutputStream(desFile);
byte buffer[] = new byte[BUFF_SIZE];
int realLength;
while ((realLength = in.read(buffer)) > 0) {
out.write(buffer, 0, realLength);
}
in.close();
out.close();
}
}

/**
* 解压文件名包含传入文字的文件
*
* @param zipFile 压缩文件
* @param folderPath 目标文件夹
* @param nameContains 传入的文件匹配名
* @throws ZipException 压缩格式有误时抛出
* @throws IOException IO错误时抛出
*/
public static ArrayList<File> upZipSelectedFile(File zipFile, String folderPath,
String nameContains) throws ZipException, IOException {
ArrayList<File> fileList = new ArrayList<File>();

File desDir = new File(folderPath);
if (!desDir.exists()) {
desDir.mkdir();
}

ZipFile zf = new ZipFile(zipFile);
for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();) {
ZipEntry entry = ((ZipEntry)entries.nextElement());
if (entry.getName().contains(nameContains)) {
InputStream in = zf.getInputStream(entry);
String str = folderPath + File.separator + entry.getName();
str = new String(str.getBytes("8859_1"), "GB2312");
// str.getBytes("GB2312"),"8859_1" 输出
// str.getBytes("8859_1"),"GB2312" 输入
File desFile = new File(str);
if (!desFile.exists()) {
File fileParentDir = desFile.getParentFile();
if (!fileParentDir.exists()) {
fileParentDir.mkdirs();
}
desFile.createNewFile();
}
OutputStream out = new FileOutputStream(desFile);
byte buffer[] = new byte[BUFF_SIZE];
int realLength;
while ((realLength = in.read(buffer)) > 0) {
out.write(buffer, 0, realLength);
}
in.close();
out.close();
fileList.add(desFile);
}
}
return fileList;
}

/**
* 获得压缩文件内文件列表
*
* @param zipFile 压缩文件
* @return 压缩文件内文件名称
* @throws ZipException 压缩文件格式有误时抛出
* @throws IOException 当解压缩过程出错时抛出
*/
public static ArrayList<String> getEntriesNames(File zipFile) throws ZipException, IOException {
ArrayList<String> entryNames = new ArrayList<String>();
Enumeration<?> entries = getEntriesEnumeration(zipFile);
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry)entries.nextElement());
entryNames.add(new String(getEntryName(entry).getBytes("GB2312"), "8859_1"));
}
return entryNames;
}

/**
* 获得压缩文件内压缩文件对象以取得其属性
*
* @param zipFile 压缩文件
* @return 返回一个压缩文件列表
* @throws ZipException 压缩文件格式有误时抛出
* @throws IOException IO操作有误时抛出
*/
public static Enumeration<?> getEntriesEnumeration(File zipFile) throws ZipException,
IOException {
ZipFile zf = new ZipFile(zipFile);
return zf.entries();

}

/**
* 取得压缩文件对象的注释
*
* @param entry 压缩文件对象
* @return 压缩文件对象的注释
* @throws UnsupportedEncodingException
*/
public static String getEntryComment(ZipEntry entry) throws UnsupportedEncodingException {
return new String(entry.getComment().getBytes("GB2312"), "8859_1");
}

/**
* 取得压缩文件对象的名称
*
* @param entry 压缩文件对象
* @return 压缩文件对象的名称
* @throws UnsupportedEncodingException
*/
public static String getEntryName(ZipEntry entry) throws UnsupportedEncodingException {
return new String(entry.getName().getBytes("GB2312"), "8859_1");
}

/**
* 压缩文件
*
* @param resFile 需要压缩的文件(夹)
* @param zipout 压缩的目的文件
* @param rootpath 压缩的文件路径
* @throws FileNotFoundException 找不到文件时抛出
* @throws IOException 当压缩过程出错时抛出
*/
private static void zipFile(File resFile, ZipOutputStream zipout, String rootpath)
throws FileNotFoundException, IOException {
rootpath = rootpath + (rootpath.trim().length() == 0 ? "" : File.separator)
+ resFile.getName();
rootpath = new String(rootpath.getBytes("8859_1"), "GB2312");
if (resFile.isDirectory()) {
File[] fileList = resFile.listFiles();
for (File file : fileList) {
zipFile(file, zipout, rootpath);
}
} else {
byte buffer[] = new byte[BUFF_SIZE];
BufferedInputStream in = new BufferedInputStream(new FileInputStream(resFile),
BUFF_SIZE);
zipout.putNextEntry(new ZipEntry(rootpath));
int realLength;
while ((realLength = in.read(buffer)) != -1) {
zipout.write(buffer, 0, realLength);
}
in.close();
zipout.flush();
zipout.closeEntry();
}
}
}

本文章简单的介绍了关于andengine入门教程之学习笔记,有需要学习的同学可以参考一下下哦。

例子中主程序.launcher.ExampleLauncher主要继承自ExpandableListActivity的列表,
这里主要定义了另个枚举public enum ExampleGroup和enum Example ,平时因为像他们这样使用比较少,值得学习。

 代码如下 复制代码

enum Example {

// ===========================================================

// Elements

// ===========================================================

 

ANALOGONSCREENCONTROL(AnalogOnScreenControlExample.class, R.string.example_analogonscreencontrol),

ANALOGONSCREENCONTROLS(AnalogOnScreenControlsExample.class, R.string.example_analogonscreencontrols),

ANIMATEDSPRITES(AnimatedSpritesExample.class, R.string.example_animatedsprites),

AUGMENTEDREALITY(AugmentedRealityExample.class, R.string.example_augmentedreality),

AUGMENTEDREALITYHORIZON(AugmentedRealityHorizonExample.class, R.string.example_augmentedrealityhorizon),

AUTOPARALLAXBACKGROUND(AutoParallaxBackgroundExample.class, R.string.example_autoparallaxbackground),

BOUNDCAMERA(BoundCameraExample.class, R.string.example_boundcamera),

CHANGEABLETEXT(ChangeableTextExample.class, R.string.example_changeabletext),

COLLISIONDETECTION(CollisionDetectionExample.class, R.string.example_collisiondetection),

COLORKEYTEXTURESOURCEDECORATOR(ColorKeyTextureSourceDecoratorExample.class, R.string.example_colorkeytexturesourcedecorator),

COORDINATECONVERSION(CoordinateConversionExample.class, R.string.example_coordinateconversion),

CUSTOMFONT(CustomFontExample.class, R.string.example_customfont),

DIGITALONSCREENCONTROL(DigitalOnScreenControlExample.class, R.string.example_digitalonscreencontrol),

EASEFUNCTION(EaseFunctionExample.class, R.string.example_easefunction),

IMAGEFORMATS(ImageFormatsExample.class, R.string.example_imageformats),

LEVELLOADER(LevelLoaderExample.class, R.string.example_levelloader),

LINE(LineExample.class, R.string.example_line),

LOADTEXTURE(LoadTextureExample.class, R.string.example_loadtexture),

MENU(MenuExample.class, R.string.example_menu),

MODPLAYER(ModPlayerExample.class, R.string.example_modplayer),

MOVINGBALL(MovingBallExample.class, R.string.example_movingball),

MULTIPLAYER(MultiplayerExample.class, R.string.example_multiplayer),

MULTITOUCH(MultiTouchExample.class, R.string.example_multitouch),

MUSIC(MusicExample.class, R.string.example_music),

PAUSE(PauseExample.class, R.string.example_pause),

PATHMODIFIER(PathModifierExample.class, R.string.example_pathmodifier),

PARTICLESYSTEMNEXUS(ParticleSystemNexusExample.class, R.string.example_particlesystemnexus),

PARTICLESYSTEMCOOL(ParticleSystemCoolExample.class, R.string.example_particlesystemcool),

PARTICLESYSTEMSIMPLE(ParticleSystemSimpleExample.class, R.string.example_particlesystemsimple),

PHYSICSCONLLISIONFILTERING(PhysicsCollisionFilteringExample.class, R.string.example_physicscollisionfiltering),

PHYSICS(PhysicsExample.class, R.string.example_physics),

PHYSICSFIXEDSTEP(PhysicsFixedStepExample.class, R.string.example_physicsfixedstep),

PHYSICSJUMP(PhysicsJumpExample.class, R.string.example_physicsjump),

PHYSICSREVOLUTEJOINT(PhysicsRevoluteJointExample.class, R.string.example_physicsrevolutejoint),

PHYSICSREMOVE(PhysicsRemoveExample.class, R.string.example_physicsremove),

PINCHZOOM(PinchZoomExample.class, R.string.example_pinchzoom),

RECTANGLE(RectangleExample.class, R.string.example_rectangle),

REPEATINGSPRITEBACKGROUND(RepeatingSpriteBackgroundExample.class, R.string.example_repeatingspritebackground),

ROTATION3D(Rotation3DExample.class, R.string.example_rotation3d),

SHAPEMODIFIER(ShapeModifierExample.class, R.string.example_shapemodifier),

SHAPEMODIFIERIRREGULAR(ShapeModifierIrregularExample.class, R.string.example_shapemodifierirregular),

SOUND(SoundExample.class, R.string.example_sound),

SPLITSCREEN(SplitScreenExample.class, R.string.example_splitscreen),

SPRITE(SpriteExample.class, R.string.example_sprite),

SPRITEREMOVE(SpriteRemoveExample.class, R.string.example_spriteremove),

STROKEFONT(StrokeFontExample.class, R.string.example_strokefont),

SUBMENU(SubMenuExample.class, R.string.example_submenu),

TEXT(TextExample.class, R.string.example_text),

TEXTMENU(TextMenuExample.class, R.string.example_textmenu),

TEXTUREOPTIONS(TextureOptionsExample.class, R.string.example_textureoptions),

TMXTILEDMAP(TMXTiledMapExample.class, R.string.example_tmxtiledmap),

TICKERTEXT(TickerTextExample.class, R.string.example_tickertext),

TOUCHDRAG(TouchDragExample.class, R.string.example_touchdrag),

UNLOADRESOURCES(UnloadResourcesExample.class, R.string.example_unloadresources),

UPDATETEXTURE(UpdateTextureExample.class, R.string.example_updatetexture),

XMLLAYOUT(XMLLayoutExample.class, R.string.example_xmllayout),

ZOOM(ZoomExample.class, R.string.example_zoom),

 

BENCHMARK_ANIMATION(AnimationBenchmark.class, R.string.example_benchmark_animation),

BENCHMARK_PARTICLESYSTEM(ParticleSystemBenchmark.class, R.string.example_benchmark_particlesystem),

BENCHMARK_PHYSICS(PhysicsBenchmark.class, R.string.example_benchmark_physics),

BENCHMARK_SHAPEMODIFIER(ShapeModifierBenchmark.class, R.string.example_benchmark_shapemodifier),

BENCHMARK_SPRITE(SpriteBenchmark.class, R.string.example_benchmark_sprite),

BENCHMARK_TICKERTEXT(TickerTextBenchmark.class, R.string.example_benchmark_tickertext),

 

APP_CITYRADAR(CityRadarActivity.class, R.string.example_app_cityradar),

 

GAME_SNAKE(SnakeGameActivity.class, R.string.example_game_snake),

GAME_RACER(RacerGameActivity.class, R.string.example_game_racer);

 

// ===========================================================

// Constants

// ===========================================================

 

// ===========================================================

// Fields

// ===========================================================

 

public final Class<? extends BaseGameActivity> CLASS;

public final int NAMERESID;

 

// ===========================================================

// Constructors

// ===========================================================

 

private Example(final Class<? extends BaseGameActivity> pExampleClass, final int pNameResID) {

this.CLASS = pExampleClass;

this.NAMERESID = pNameResID;

}

 

// ===========================================================

// Getter & Setter

// ===========================================================

 

// ===========================================================

// Methods for/from SuperClass/Interfaces

// ===========================================================

 

// ===========================================================

// Methods

// ===========================================================

 

// ===========================================================

// Inner and Anonymous Classes

// ===========================================================

}

上面的public final Class<? extends BaseGameActivity> CLASS;表示任何继承自BaseGameActivity的类型,属于泛型,
因为andengine的例子程序都是继承自BaseGameActivity。

 代码如下 复制代码

public enum ExampleGroup {

// ===========================================================

// Elements

// ===========================================================

 

SIMPLE(R.string.examplegroup_simple,

Example.LINE, Example.RECTANGLE, Example.SPRITE, Example.SPRITEREMOVE),

MODIFIER_AND_ANIMATION(R.string.examplegroup_modifier_and_animation,

Example.MOVINGBALL, Example.SHAPEMODIFIER, Example.SHAPEMODIFIERIRREGULAR, Example.PATHMODIFIER, Example.ANIMATEDSPRITES, Example.EASEFUNCTION, Example.ROTATION3D ),

TOUCH(R.string.examplegroup_touch,

Example.TOUCHDRAG, Example.MULTITOUCH, Example.ANALOGONSCREENCONTROL, Example.DIGITALONSCREENCONTROL, Example.ANALOGONSCREENCONTROLS, Example.COORDINATECONVERSION, Example.PINCHZOOM),

PARTICLESYSTEM(R.string.examplegroup_particlesystems,

Example.PARTICLESYSTEMSIMPLE, Example.PARTICLESYSTEMCOOL, Example.PARTICLESYSTEMNEXUS),

MULTIPLAYER(R.string.examplegroup_multiplayer,

Example.MULTIPLAYER),

PHYSICS(R.string.examplegroup_physics,

Example.COLLISIONDETECTION, Example.PHYSICS, Example.PHYSICSFIXEDSTEP, Example.PHYSICSCONLLISIONFILTERING, Example.PHYSICSJUMP, Example.PHYSICSREVOLUTEJOINT, Example.PHYSICSREMOVE ),

TEXT(R.string.examplegroup_text,

Example.TEXT, Example.TICKERTEXT, Example.CHANGEABLETEXT, Example.CUSTOMFONT, Example.STROKEFONT),

AUDIO(R.string.examplegroup_audio,

Example.SOUND, Example.MUSIC, Example.MODPLAYER),

ADVANCED(R.string.examplegroup_advanced,

Example.SPLITSCREEN, Example.BOUNDCAMERA ), // Example.AUGMENTEDREALITY, Example.AUGMENTEDREALITYHORIZON),

BACKGROUND(R.string.examplegroup_background,

Example.REPEATINGSPRITEBACKGROUND, Example.AUTOPARALLAXBACKGROUND, Example.TMXTILEDMAP),

OTHER(R.string.examplegroup_other,

Example.PAUSE, Example.MENU, Example.SUBMENU, Example.TEXTMENU, Example.ZOOM , Example.IMAGEFORMATS, Example.TEXTUREOPTIONS, Example.COLORKEYTEXTURESOURCEDECORATOR, Example.LOADTEXTURE, Example.UPDATETEXTURE, Example.XMLLAYOUT, Example.LEVELLOADER),

APP(R.string.examplegroup_app,

Example.APP_CITYRADAR),

GAME(R.string.examplegroup_game,

Example.GAME_SNAKE, Example.GAME_RACER),

BENCHMARK(R.string.examplegroup_benchmark,

Example.BENCHMARK_SPRITE, Example.BENCHMARK_SHAPEMODIFIER, Example.BENCHMARK_ANIMATION, Example.BENCHMARK_TICKERTEXT, Example.BENCHMARK_PARTICLESYSTEM, Example.BENCHMARK_PHYSICS);

 

// ===========================================================

// Constants

// ===========================================================

 

// ===========================================================

// Fields

// ===========================================================

public final Example[] EXAMPLES;

public final int NAMERESID;

 

// ===========================================================

// Constructors

// ===========================================================

 

private ExampleGroup(final int pNameResID, final Example ... pExamples) {

this.NAMERESID = pNameResID;

this.EXAMPLES = pExamples;

}

 

// ===========================================================

// Getter & Setter

// ===========================================================

 

// ===========================================================

// Methods for/from SuperClass/Interfaces

// ===========================================================

 

// ===========================================================

// Methods

// ===========================================================

 

// ===========================================================

// Inner and Anonymous Classes

// ===========================================================

}

主程序就比较简单,不再介绍了。

本文章分享一篇关于手机开的中的AndroidPN环境建立图文教程,有需要开发android各种应用的朋友可以参考一下本文章哦。
AndroidPN实现了从服务器到android移动平台的文本消息推送。这里先简单说一下androidPN的安装过程。
下载androidpn-client-0.5.0.zip和androidpn-server-0.5.0-bin.zip
网址:http://sourceforge.net/projects/androidpn/ 
解压两个包,Eclipse导入client,配置好目标平台,打开raw/androidpn.properties文件,
 代码如下 复制代码
apiKey=1234567890
xmppHost=10.0.2.2
xmppPort=5222
如果是模拟器来运行客户端程序,把xmppHost配置成10.0.2.2 (模拟器把10.0.2.2认为是所在主机的地址,127.0.0.1是模拟器本身的回环地址).
 代码如下 复制代码
xmppPort=5222 是服务器的xmpp服务监听端口
运行
 代码如下 复制代码
androidpn-server-0.5.0binrun.bat
启动服务器,从浏览器访问
 代码如下 复制代码
http://127.0.0.1:7070/index.do (androidPN Server
有个轻量级的web服务器,在7070端口监听请求,接受用户输入的文本消息)
运行客户端,客户端会向服务器发起连接请求,注册成功后,服务器能识别客户端,并维护和客户端的IP长连接
 进入Notifications界面,输入消息发送
模拟器客户端接受到server推送的消息
这样AndroidPN的环境就搭好了,下一步我将深入研究研究实行以及XMPP协议。
本文章介绍关于在android开发中的图片的浏览、缩放、拖动和自动居中实现实例,有需要的同学可以参考一下下本文章。

 

Touch.java

 代码如下 复制代码

/**
 * 图片浏览、缩放、拖动、自动居中
 */
public class Touch extends Activity implements OnTouchListener {

    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();
    DisplayMetrics dm;
    ImageView imgView;
    Bitmap bitmap;

    float minScaleR;// 最小缩放比例
    static final float MAX_SCALE = 4f;// 最大缩放比例

    static final int NONE = 0;// 初始状态
    static final int DRAG = 1;// 拖动
    static final int ZOOM = 2;// 缩放
    int mode = NONE;

    PointF prev = new PointF();
    PointF mid = new PointF();
    float dist = 1f;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.scale);
        imgView = (ImageView) findViewById(R.id.imag);// 获取控件
        bitmap = BitmapFactory.decodeResource(getResources(), this.getIntent()
                .getExtras().getInt("IMG"));// 获取图片资源
        imgView.setImageBitmap(bitmap);// 填充控件
        imgView.setOnTouchListener(this);// 设置触屏监听
        dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);// 获取分辨率
        minZoom();
        center();
        imgView.setImageMatrix(matrix);
    }

    /**
     * 触屏监听
     */
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        // 主点按下
        case MotionEvent.ACTION_DOWN:
            savedMatrix.set(matrix);
            prev.set(event.getX(), event.getY());
            mode = DRAG;
            break;
        // 副点按下
        case MotionEvent.ACTION_POINTER_DOWN:
            dist = spacing(event);
            // 如果连续两点距离大于10,则判定为多点模式
            if (spacing(event) > 10f) {
                savedMatrix.set(matrix);
                midPoint(mid, event);
                mode = ZOOM;
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                matrix.set(savedMatrix);
                matrix.postTranslate(event.getX() - prev.x, event.getY()
                        - prev.y);
            } else if (mode == ZOOM) {
                float newDist = spacing(event);
                if (newDist > 10f) {
                    matrix.set(savedMatrix);
                    float tScale = newDist / dist;
                    matrix.postScale(tScale, tScale, mid.x, mid.y);
                }
            }
            break;
        }
        imgView.setImageMatrix(matrix);
        CheckView();
        return true;
    }

    /**
     * 限制最大最小缩放比例,自动居中
     */
    private void CheckView() {
        float p[] = new float[9];
        matrix.getValues(p);
        if (mode == ZOOM) {
            if (p[0] < minScaleR) {
                matrix.setScale(minScaleR, minScaleR);
            }
            if (p[0] > MAX_SCALE) {
                matrix.set(savedMatrix);
            }
        }
        center();
    }

    /**
     * 最小缩放比例,最大为100%
     */
    private void minZoom() {
        minScaleR = Math.min(
                (float) dm.widthPixels / (float) bitmap.getWidth(),
                (float) dm.heightPixels / (float) bitmap.getHeight());
        if (minScaleR < 1.0) {
            matrix.postScale(minScaleR, minScaleR);
        }
    }

    private void center() {
        center(true, true);
    }

    /**
     * 横向、纵向居中
     */
    protected void center(boolean horizontal, boolean vertical) {

        Matrix m = new Matrix();
        m.set(matrix);
        RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
        m.mapRect(rect);

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

        float deltaX = 0, deltaY = 0;

        if (vertical) {
            // 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下放留空则往下移
            int screenHeight = dm.heightPixels;
            if (height < screenHeight) {
                deltaY = (screenHeight - height) / 2 - rect.top;
            } else if (rect.top > 0) {
                deltaY = -rect.top;
            } else if (rect.bottom < screenHeight) {
                deltaY = imgView.getHeight() - rect.bottom;
            }
        }

        if (horizontal) {
            int screenWidth = dm.widthPixels;
            if (width < screenWidth) {
                deltaX = (screenWidth - width) / 2 - rect.left;
            } else if (rect.left > 0) {
                deltaX = -rect.left;
            } else if (rect.right < screenWidth) {
                deltaX = screenWidth - rect.right;
            }
        }
        matrix.postTranslate(deltaX, deltaY);
    }

    /**
     * 两点的距离
     */
    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);
    }

    /**
     * 两点的中点
     */
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }
}

 

scale.xml

 代码如下 复制代码

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="center" >

    <ImageView
        android:id="@+id/imag"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center"
        android:scaleType="matrix" >
    </ImageView>

</FrameLayout>

标签:[!--infotagslink--]

您可能感兴趣的文章: