第一步:创建手势基类:
public abstract class BaseGuestureDetector {
/** 进行中的手势 */
protected boolean mIsGestureMoving;
/** 先前的事件 */
protected MotionEvent mPreMotionEvent;
/** 当前的事件 */
protected MotionEvent mCurrentMotionEvent;
public Context mContext;
public BaseGuestureDetector(Context context){
mContext = context;
}
public boolean onTouchEvent(MotionEvent event){
if (!mIsGestureMoving) {
handleStartProgressEvent(event);
}else {
handleInProgressEvent(event);
}
return true;
}
protected abstract void handleInProgressEvent(MotionEvent event);
protected abstract void handleStartProgressEvent(MotionEvent event);
protected abstract void updateStateByEvent(MotionEvent event);
protected void resetState(){
if (mPreMotionEvent != null) {
mPreMotionEvent.recycle();
mPreMotionEvent = null;
}
if (mCurrentMotionEvent != null) {
mCurrentMotionEvent.recycle();
mCurrentMotionEvent = null;
}
mIsGestureMoving = false;
}
}
第二步:根据基类创建手势类
public class MoveGestureDetector extends BaseGuestureDetector {
/** 当前的手指位置 */
private PointF mCurrentPointF;
/** 上次的手指位置 */
private PointF mPrePointF;
/** 用于记录最终结果,并返回 */
private PointF mExtenalPointer = new PointF();
private OnMoveGestureListener mListener;
public MoveGestureDetector(Context context, OnMoveGestureListener listener) {
super(context);
this.mListener = listener;
}
/**
* 处理正在进行的动作
*/
@Override
protected void handleInProgressEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
switch (action) {
// 手指弹起与离开时
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mListener.onMoveEnd(this);
resetState();
break;
// 手指移动
case MotionEvent.ACTION_MOVE:
updateStateByEvent(event);
boolean move = mListener.onMove(this);
if (move) {
mPreMotionEvent.recycle();
mPreMotionEvent = MotionEvent.obtain(event);
}
break;
default:
break;
}
}
/**
* 处理开始的事件
*/
@Override
protected void handleStartProgressEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
switch (action) {
case MotionEvent.ACTION_DOWN:
// 防止没有接收到CANCEL or UP ,保险起见
resetState();
// 初始化
mPreMotionEvent = MotionEvent.obtain(event);
updateStateByEvent(event);
break;
case MotionEvent.ACTION_MOVE:
mIsGestureMoving = mListener.onMoveBegin(this);
break;
default:
break;
}
}
@Override
protected void updateStateByEvent(MotionEvent event) {
final MotionEvent prev = mPreMotionEvent;
// 计算开始点的位置
mPrePointF = caculateFocalPointer(prev);
mCurrentPointF = caculateFocalPointer(event);
Log.e("TAG", mPrePointF.toString() + " , " + mCurrentPointF);
// 是否跳过这个点,如果前后手指数不一样
boolean mSkipThisMoveEvent = prev.getPointerCount() != event.getPointerCount();
// 如果是无效的设置为0
mExtenalPointer.x = mSkipThisMoveEvent ? 0 : mCurrentPointF.x - mPrePointF.x;
mExtenalPointer.y = mSkipThisMoveEvent ? 0 : mCurrentPointF.y - mPrePointF.y;
}
/**
* 根据event计算多指中心点
*
* @param event
* @return
*/
private PointF caculateFocalPointer(MotionEvent event) {
final int count = event.getPointerCount();
float x = 0, y = 0;
for (int i = 0; i < count; i++) {
x += event.getX(i);
y += event.getY(i);
}
// 取手指的中心点
x = x / count;
y = y / count;
return new PointF(x, y);
}
/**
* 向外暴露的两个方法,获得移动中的位置
*
* @return
*/
public float getMoveX() {
return mExtenalPointer.x;
}
public float getMoveY() {
return mExtenalPointer.y;
}
/**
* 回调函数
*
* @Project App_View
* @Package com.android.view.largeimageview
* @author chenlin
* @version 1.0
* @Note TODO
*/
public interface OnMoveGestureListener {
/**
* 手指开始移动
*
* @param detector
* @return
*/
public boolean onMoveBegin(MoveGestureDetector detector);
/**
* 手指移动中
*
* @param detector
* @return
*/
public boolean onMove(MoveGestureDetector detector);
/**
* 移动结束
*
* @param detector
*/
public void onMoveEnd(MoveGestureDetector detector);
}
public static class SimpleMoveGestureDetector implements OnMoveGestureListener {
@Override
public boolean onMoveBegin(MoveGestureDetector detector) {
return true;
}
@Override
public boolean onMove(MoveGestureDetector detector) {
return false;
}
@Override
public void onMoveEnd(MoveGestureDetector detector) {
}
}
}
第三步:自定义LargeImageView
public class LargeImageView extends View {
/**图片的选择的区域 */
private BitmapRegionDecoder mDecoder;
/**图片的宽度和高度 */
private int mImageWidth, mImageHeight;
/**绘制的区域*/
private volatile Rect mRect = new Rect();
/**移动时手势*/
private MoveGestureDetector mDetector;
/**
* Creates Bitmap objects from various sources, including files, streams,
* and byte-arrays.
*/
private static final BitmapFactory.Options options = new BitmapFactory.Options();
static{
/*设置让解码器以最佳方式解码*/
options.inPreferredConfig = Bitmap.Config.RGB_565;
}
public LargeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public LargeImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LargeImageView(Context context) {
super(context);
init();
}
//初始化手势
private void init() {
mDetector = new MoveGestureDetector(getContext(), new SimpleMoveGestureDetector(){
@Override
public boolean onMove(MoveGestureDetector detector) {
// 移动时
int moveX = (int) detector.getMoveX();
int moveY = (int) detector.getMoveY();
Logger.i("large", "moveX == " + moveX);
Logger.i("large", "moveY == " + moveY);
//如果图片的宽度>view的宽度
if (mImageWidth > getWidth()) {
//向左移动
mRect.offset(-moveX, 0);
checkWidth();
//重构
invalidate();
}
if (mImageHeight > getHeight()) {
//向上移动
mRect.offset(0, -moveY);
checkHeight();
//重构
invalidate();
}
return true;
}
});
}
// private OnMoveGestureListener listener = new OnMoveGestureListener(){
//
// @Override
// public boolean onMoveBegin(MoveGestureDetector detector) {
// //Toast.makeText(getContext(), "开始移动", 1).show();
// return false;
// }
//
// @Override
// public boolean onMove(MoveGestureDetector detector) {
// // 移动时
// int moveX = (int) detector.getMoveX();
// int moveY = (int) detector.getMoveY();
// //如果图片的宽度>view的宽度
// if (mImageWidth > getWidth()) {
// //向左移动
// mRect.offset(-moveX, 0);
// checkWidth();
// //重构
// invalidate();
// }
// if (mImageHeight > getHeight()) {
// //向上移动
// mRect.offset(0, -moveY);
// checkHeight();
// //重构
// invalidate();
// }
// return true;
// }
//
// @Override
// public void onMoveEnd(MoveGestureDetector detector) {
// //Toast.makeText(getContext(), "移动停止", 1).show();
// }
//
// };
/**
* 把图片的宽度归位
*/
protected void checkWidth() {
Rect rect = mRect;
int width = mImageWidth;
//图片的右边 > view
if (rect.right > width) {
rect.right = width;
//左边 = 图片的宽度 - 视图宽度
rect.left = width - getWidth();
}
//在屏幕外
if (rect.left < 0) {
rect.left = 0;
//右边 = 视图宽度
rect.right = getWidth();
}
}
/**
* 图片的高度归位
*/
protected void checkHeight() {
Rect rect = mRect;
int height = mImageHeight;
if (rect.bottom > height) {
rect.bottom = height;
rect.top = height - getHeight();
}
if (rect.top < 0) {
rect.top = 0;
rect.bottom = getHeight();
}
}
/**
* 第一步:加载图片后,显示图片的中心位置
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//指的是视图的测量宽度
int widthMeasure = getMeasuredWidth();
int heightMeasure = getMeasuredHeight();
//图片实际的宽度
int imageWidth = mImageWidth;
int imageHeight = mImageHeight;
//默认直接显示图片的中心区域,可以自己去调节
mRect.left = (imageWidth - widthMeasure)/2;
mRect.top = (imageHeight - heightMeasure)/2;
mRect.right = mRect.left + widthMeasure;
mRect.bottom = mRect.top + heightMeasure;
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 第二步:把图片的事件交由手势来处理
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
//touchevent事件有手势来处理
mDetector.onTouchEvent(event);
return true;
}
@Override
protected void onDraw(Canvas canvas) {
Bitmap bm = mDecoder.decodeRegion(mRect, options);
//从左上角度开始画
canvas.drawBitmap(bm, 0, 0, null);
super.onDraw(canvas);
}
/**
* 向外提供加载图片后得到的输入流
* @param is
* @return
*/
protected void setInputStream(InputStream is){
try {
//得到要加载显示的图片区域
mDecoder = BitmapRegionDecoder.newInstance(is, false);
BitmapFactory.Options tmpOptions = new BitmapFactory.Options();
tmpOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, tmpOptions);
//获得图片的宽高
mImageHeight = tmpOptions.outHeight;
mImageWidth = tmpOptions.outWidth;
} catch (IOException e) {
e.printStackTrace();
} finally{
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
第四步:实现
public class MainActivity extends Activity {
private LargeImageView mImageview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_largeimage);
mImageview = (LargeImageView) findViewById(R.id.largeImage);
loadImage();
}
/**
* 从asset文件夹里加载图片
*/
private void loadImage() {
try {
InputStream is = getAssets().open("22.jpg");
mImageview.setInputStream(is);
} catch (IOException e) {
e.printStackTrace();
}
}
}
activity_largeimage.xml文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.android.view.largeimageview.LargeImageView
android:id="@+id/largeImage"
android:layout_width="match_parent"
android:layout_height="match_parent" >
com.android.view.largeimageview.LargeImageView>
RelativeLayout>
—————————————————————————————————————————————————–
下载地址:
https://item.taobao.com/item.htm?id=558680925808
———————-课程目录——————————
第01项目:OA办公自动化项目(四套)
第02项目:CRM客户关系管理项目(两套)
第03项目:宅急送项目
第04项目:杰信商贸SSH版
第05项目:电力项目(两套)
第06项目:校内网项目
第07项目:Java邮件开发教程
第08项目:java网上在线支付实战视频
第09项目:俄罗斯方块游戏开发_视频教程
第10项目:交通灯管理系统视频教程
第11项目:银行业务调度系统视频教程
第12项目:供应链系统视频教程
第13项目:网上商城项目
第14项目:药品集中采购系统视频教程
第15项目:杰信商贸SSM版
第16项目:国家税务协同平台项目
第17项目:javaWeb聊天室
第18项目:点餐系统
第19项目:网上书店
第20项目:手机进销存系统
—————————————————————————————————————————————————–