您的位置:首页 > 移动开发 > Android开发

Android 点击图片放大展示 展示中可调节图片的缩放显示 图片查看器

2017-01-09 21:48 501 查看
1.首先需要初始化一个全局常量

这个是常量的工具类

public final class GlobalConstant {

private static int DEVICE_WIDTH;
private static int DEVICE_HEIGHT;
private static float DEVICE_DENSITY;

public static void initDeviceInfo(Context context) {
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(metrics);
DEVICE_WIDTH = metrics.widthPixels;
DEVICE_HEIGHT = metrics.heightPixels;
DEVICE_DENSITY = metrics.density;
}

public static int getDeviceWidth() {
return DEVICE_WIDTH;
}

public static int getDeviceHeight() {
return DEVICE_HEIGHT;
}

public static float getDeviceDensity() {
return DEVICE_DENSITY;
}
}


初始化的方法就是在程序的Application类对的oncreat方法中执行

GlobalConstant.initDeviceInfo(this);


2.可缩放的ImageView

public class GestureImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener {

private static final String TAG = GestureImageView.class.getSimpleName();
private boolean isOnce = true;
//初始缩放值
private float currentScale;
private static int mWidth = GlobalConstant.getDeviceWidth();
private static int mHeight = GlobalConstant.getDeviceHeight();
private static int mDistance = (int) Math.sqrt((Math.pow(mWidth, 2) + Math.pow(mHeight, 2)));
private final float MAX_SCALE = 4.0f; // 修改这个值可以修改缩放最大值
private float MIN_SCALE;
private float[] mMatrixValues = new float[9];
private float[] initMatrixValues = new float[9];
private Matrix mMatrix = new Matrix();
private PointF scalePointF;
private PointF dragPointF;
private float preDistance = 0;
private static final int SCALE_RATE = 4;//修改此值用以修改缩放速率

public GestureImageView(Context context) {
super(context);
initImageAttribute();
}

public GestureImageView(Context context, AttributeSet attrs) {
super(context, attrs);
initImageAttribute();
}

public GestureImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initImageAttribute();
}

/**
* 初始化图像属性
*/
private void initImageAttribute() {
setScaleType(ScaleType.MATRIX);
setFocusable(true);// 触摸事件开启此参数用以搞事情
catchTouchEvent(true);
}

/**
* 是否捕获touch事件
*
* @param flag true捕获touch事件,false不捕获
*/
public void catchTouchEvent(boolean flag) {
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(flag);
}
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
getViewTreeObserver().addOnGlobalLayoutListener(null);
}
}

@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
adjustImageMatrix();
}

@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
adjustImageMatrix();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
catchTouchEvent(true);
scalePointF = null;
preDistance = 0;
dragPointF = null;
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() == 2) { //两点触摸事件处理
handleScaleEvent(event);
}
if (event.getPointerCount() == 1) { //处理移动事件
handleDragEvent(event);
}
break;
case MotionEvent.ACTION_POINTER_UP:
11ee7

if (event.getPointerCount() != 1) {
scalePointF = null;
preDistance = 0;
dragPointF = null;
}
break;
case MotionEvent.ACTION_UP:
dragPointF = null;
break;
default:
break;
}
return true;
}

/**
* 处理拖拽手势
*
* @param event 触摸Event
*/
private void handleDragEvent(MotionEvent event) {
scalePointF = null;
if (dragPointF == null) {
dragPointF = new PointF(event.getX(), event.getY());
} else {
float x = event.getX();
float y = event.getY();
drag(x - dragPointF.x,
y - dragPointF.y);
dragPointF = new PointF(x, y);
}
}

/**
* 处理缩放手势
*
* @param event 事件
*/
private void handleScaleEvent(MotionEvent event) {
dragPointF = null;
float fX = event.getX(0);
float fY = event.getY(0);
float sX = event.getX(1);
float sY = event.getY(1);
float distance = (float) Math.sqrt((Math.pow(fX - sX, 2) + Math.pow(fY - sY, 2)));
if (scalePointF == null) {
scalePointF = new PointF((fX + sX) / 2.0f, (fY + sY) / 2.0f);
preDistance = distance;
} else {
float scale = (distance - preDistance) / mDistance * SCALE_RATE;//修改这个值可以更改缩放速率
float judge = currentScale + scale;
scale = judge > MAX_SCALE || judge < MIN_SCALE ?
(judge > MAX_SCALE ? MAX_SCALE - currentScale : MIN_SCALE - currentScale) :
scale;
currentScale += scale;
scale(currentScale / (currentScale - scale), scalePointF);
}
preDistance = distance;
}

/**
* 根据图像矩形处理拖拽的X值
*
* @param rect  图像矩形
* @param dragX 拖拽的X值
* @return 处理以后dragX值
*/
private float handleDragX(RectF rect, float dragX) {
if (rect.left < 0 || rect.right > mWidth) { // 放大时,如果内容宽度大于屏幕,左右边界不能出现黑边
if (rect.left + dragX > 0) {
dragX = 0 - rect.left;
} else if (rect.right + dragX < mWidth) {
dragX = mWidth - rect.right;
}
} else {
dragX = 0;
}
return dragX;
}

/**
* 根据图像矩形处理拖拽的Y值
*
* @param rect  图像矩形
* @param dragY 拖拽的Y值
* @return 处理以后dragY值
*/
private float handleDragY(RectF rect, float dragY) {
if (rect.top <= 0 && rect.bottom >= mHeight) { // 放大时,如果内容宽度大于屏幕,左右边界不能出现黑边
if (rect.top + dragY > 0) {
dragY = 0 - rect.top;
} else if (rect.bottom + dragY < mHeight) {
dragY = mHeight - rect.bottom;
}
} else {
dragY = 0;
}
return dragY;
}

/**
* 拖拽imageView
*
* @param dragX X轴的移动距离
* @param dragY Y轴的移动距离
*/
private void drag(float dragX, float dragY) {
RectF rect = getImageRectF();
catchTouchEvent(canDrag(rect));
dragX = handleDragX(rect, dragX);
dragY = handleDragY(rect, dragY);
mMatrix.postTranslate(dragX, dragY);
setImageMatrix(mMatrix);
mMatrix.getValues(mMatrixValues);
}

/**
* 根据ImageView当前位置判断是否可以拖拽
*
* @param currentRect 当前的矩形
* @return true可以拖拽,false不可以
*/
private boolean canDrag(RectF currentRect) {
RectF preRect = getInitialRectF();
boolean canDrag;
if (preRect.left > 0) {
canDrag = !(currentRect.left >= 0 || currentRect.right <= mWidth || (currentRect.left > 0 && currentScale == MAX_SCALE));
} else {
canDrag = !(currentRect.left == 0 || currentRect.right == mWidth);
}
return canDrag;
}

/**
* 获取初始的图像矩形
*
* @return
*/
private RectF getInitialRectF() {
Matrix preMatrix1 = new Matrix();
preMatrix1.setValues(initMatrixValues);
return getImageRectF(preMatrix1);
}

/**
* 缩放时,处理边缘不过界
*
* @param matrix 拷贝的矩阵
* @param scale  缩放比例
* @param f      缩放中心点
* @return 返回X坐标的点
*/
private float handleScaleDragX(Matrix matrix, float scale, PointF f) {
matrix.postScale(scale, scale, f.x, mHeight / 2.0f);
RectF rect = getImageRectF(matrix); // 根据拷贝过后的矩阵计算得出的矩形
RectF preRect = getInitialRectF();
float x = f.x;
if (preRect.left > 0) { // 图片初始矩形宽度小于屏幕宽度
x = rect.left > 0 || rect.right < mWidth ? mWidth / 2.0f : x;
} else {
x = rect.left > 0 ? 0 : (rect.right < mWidth ? mWidth : x);
}
return x;
}

/**
* 按照缩放比例和点进行缩放
*
* @param scale 缩放比例
* @param f     包含缩放中心点的PointF
*/
private void scale(float scale, PointF f) {
LogUtil.showLog("缩放的比率:scale", scale+"");
if (scale<=(float)1.00) {
scale=(float) 1.00;
}
Matrix matrix = new Matrix(mMatrix);
mMatrix.postScale(scale, scale, handleScaleDragX(matrix, scale, f), mHeight / 2.0f);
mMatrix.getValues(mMatrixValues);
//        getImageRectF();
if (currentScale == MIN_SCALE) {// 缩放到初始位置,将图片设置为初始位置,此处可以添加动画,请随意发挥。
mMatrix.setValues(initMatrixValues);
setImageMatrix(mMatrix);
}
Log.i(TAG, "currentScale = " + currentScale);
setImageMatrix(mMatrix);
}

/**
* 将图像调整到适合的位置
*/
private void adjustImageMatrix() {
Drawable d = getDrawable();
if (d == null) {
setImageResource(R.drawable.ic_launcher);
return;
}
int width = d.getIntrinsicWidth();
int height = d.getIntrinsicHeight();
float scale = 1.0f;
// 有3种情况,1、宽大于屏幕宽。2、高大于屏幕高。3、宽和高均大于屏幕,图像宽高均小于设备的暂时不考虑
if (width > mWidth && height < mHeight) {
scale = mWidth * 1.0f / width;
}
if (height > mHeight && width < mWidth) {
scale = mHeight * 1.0f / height;
}
if (height > mHeight && width > mWidth) {
scale = Math.min(mWidth * 1.0f / width, mHeight * 1.0f / height);
}
currentScale = scale;
MIN_SCALE = scale;
mMatrix = new Matrix();
mMatrix.postTranslate((mWidth - width) / 2.0f, (mHeight - height) / 2.0f);
mMatrix.postScale(currentScale, currentScale, mWidth / 2.0f, mHeight / 2.0f);
mMatrix.getValues(mMatrixValues);
mMatrix.getValues(initMatrixValues);
setImageMatrix(mMatrix);
getImageRectF();

}

/**
* 返回Drawable的矩形
*
* @param matrix 拷贝出来的矩阵
* @return imageView矩形数据
*/
private RectF getImageRectF(Matrix matrix) {
RectF rect = new RectF();
Drawable d = getDrawable();
if (d != null) {
rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
matrix.mapRect(rect);
}
return rect;
}

/**
* 返回Drawable的矩形
*
* @return imageView矩形数据
*/
private RectF getImageRectF() {
RectF rect = new RectF();
Drawable d = getDrawable();
if (d != null) {
rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
mMatrix.mapRect(rect);
}
return rect;
}

@Override
public void onGlobalLayout() {
if (isOnce) {
isOnce = false;
adjustImageMatrix();
}
}
}


3.用于展示图片的Activity

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.ViewGroup.LayoutParams;

public class PhotoActivity extends Activity {

private ArrayList<GestureImageView> listViews = null;
private ViewPager pager;
private MyPageAdapter adapter;

public List<Bitmap> bmp = new ArrayList<Bitmap>();
public int max;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo);

for (int i = 0; i < Bimp.bmp.size(); i++) {
bmp.add(Bimp.bmp.get(i));
}
max = Bimp.max;

pager = (ViewPager) findViewById(R.id.viewpager);
pager.setOnPageChangeListener(pageChangeListener);
pager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
for (int i = 0; i < bmp.size(); i++) {
initListViews(bmp.get(i));
}

adapter = new MyPageAdapter(listViews);// 构造adapter
pager.setAdapter(adapter);// 设置适配器
Intent intent = getIntent();
int id = intent.getIntExtra("ID", 0);
pager.setCurrentItem(id);
}

@SuppressWarnings("deprecation")
private void initListViews(Bitmap bm) {
if (listViews == null)
listViews = new ArrayList<GestureImageView>();
GestureImageView img = new GestureImageView(this);// 构造textView对象
img.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
img.setBackgroundColor(0xff000000);
img.setImageBitmap(bm);
img.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.FILL_PARENT));
listViews.add(img);// 添加view
}

private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {

public void onPageSelected(int arg0) {// 页面选择响应函数
}

public void onPageScrolled(int arg0, float arg1, int arg2) {// 滑动中。。。

}

public void onPageScrollStateChanged(int arg0) {// 滑动状态改变

}
};

class MyPageAdapter extends PagerAdapter {

private ArrayList<GestureImageView> listViews;// content

private int size;// 页数

public MyPageAdapter(ArrayList<GestureImageView> listViews) {// 构造函数
// 初始化viewpager的时候给的一个页面
this.listViews = listViews;
size = listViews == null ? 0 : listViews.size();
}

public void setListViews(ArrayList<GestureImageView> listViews) {// 自己写的一个方法用来添加数据
this.listViews = listViews;
size = listViews == null ? 0 : listViews.size();
}

public int getCount() {// 返回数量
return size;
}

public int getItemPosition(Object object) {
return POSITION_NONE;
}

public void destroyItem(View arg0, int arg1, Object arg2) {// 销毁view对象
((ViewPager) arg0).removeView(listViews.get(arg1 % size));
}

public void finishUpdate(View arg0) {
}

public Object instantiateItem(View arg0, int arg1) {// 返回view对象
try {
((ViewPager) arg0).addView(listViews.get(arg1 % size), 0);

} catch (Exception e) {
LogUtil.showLogerror("执行instantiateItem方法时报错:", e.toString());
}
return listViews.get(arg1 % size);
}

public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}

}
}


此Activity的布局文件是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>

</RelativeLayout>


4.主体都写完了,接下来就是调用了

博主是这样调用的。

Bitmap bm = Bimp.revitionImageSize(path);
//图片的本地路径
Bimp.bmp.add(bm);
Intent intent = new Intent(ctx,PhotoActivity.class);
intent.putExtra("ID", 0);
ctx.startActivity(intent);


后续,其实Bimp.bmp.add(bm);在这句代码里再添加的时候,可以实现左右滑动来展示图片,毕竟我们用的是ViewPager,但是博主在项目中展示的时候,需要实现微信的效果,还没有构思出符合项目已有代码的逻辑,得加油啦。。。

5.此篇文章,我其实结合了在网上查找的两个Demo。

说什么我都不能确定那两个Demo的源码地址了,太对不起作者了,我已免费资源的方式放到这两个网址中:

明天评论里补这两个Demo的地址,今天这资源我是传不上去了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android