Gallery + ViewPager实现图片浏览器

来源:互联网 发布:手机mac地址伪装 编辑:程序博客网 时间:2024/05/21 09:09
相信很多人在开发中都有做过图片浏览或者是预览的功能,但我想大多数人会和我一样,百度一下仿微信发说说,然后下载个demo,直接把demo拷到自己的代码进行一些简单的修改,完成该有的效果就ok了,从不去仔细的去看别人的代码。再随着越来越多开源框架的出来,我们已习惯了用别人的东西,渐渐的忘记了怎么去写。浑浑噩噩过了这么长时间了,反省了,我也想自己写点东西了,向csdn大神学习。
本文参考http://blog.csdn.net/lmj623565791/article/details/39480503 鸿洋大神的博客,谢谢;

先分析一下图片预览功能,能够切换并显示图片,对选中的图片进行缩放处理。
首先来第一步:对图片进行切换和浏览
上代码
布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.v4.view.ViewPager        android:id="@+id/viewpager"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        ></android.support.v4.view.ViewPager>    <Gallery        android:id="@+id/gallery"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:unselectedAlpha="0.6"        android:spacing="10dp"        ></Gallery></LinearLayout>
然后是代码,很简单,就是分别给gallery和viewpager设置设配器,然后两者中有一个改变时,切换另一个的=显示条目;
package com.hpl.demo_application;import android.app.Activity;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.Gallery;import android.widget.ImageView;import java.util.ArrayList;/** * Created by 79115 on 2016/12/1. */public class TestActivity extends Activity {    private int[] images = {R.drawable.icon_001, R.drawable.icon_002, R.drawable.icon_003, R.drawable.icon_004, R.drawable.icon_005, R.drawable.icon_006};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.test);        final Gallery gallery = (Gallery) findViewById(R.id.gallery);        final ViewPager viewpager = (ViewPager) findViewById(R.id.viewpager);        final ArrayList<View> views = new ArrayList<View>();        gallery.setAdapter(new BaseAdapter() {            @Override            public int getCount() {                return images.length;            }            @Override            public Object getItem(int i) {                return null;            }            @Override            public long getItemId(int i) {                return 0;            }            @Override            public View getView(int i, View view, ViewGroup viewGroup) {                ImageView imageView = new ImageView(TestActivity.this);                imageView.setScaleType(ImageView.ScaleType.FIT_XY);                imageView.setLayoutParams(new Gallery.LayoutParams(100, 75));                imageView.setImageResource(images[i % images.length]);                return imageView;            }        });        viewpager.setAdapter(new PagerAdapter() {            @Override            public int getCount() {                return images.length;            }            @Override            public boolean isViewFromObject(View view, Object object) {                return view == object;            }            @Override            public Object instantiateItem(ViewGroup container, int position) {                ImageView imageView = new ImageView(TestActivity.this);                imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);                imageView.setImageResource(images[position % images.length]);                views.add(imageView);                container.addView(imageView);                return imageView;            }            @Override            public void destroyItem(ViewGroup container, int position, Object object) {                container.removeView(views.get(position));            }        });        viewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            }            @Override            public void onPageSelected(int position) {                int selectedItemPosition = gallery.getSelectedItemPosition();                if(position != selectedItemPosition)                gallery.setSelection(position);            }            @Override            public void onPageScrollStateChanged(int state) {            }        });        gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {            @Override            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {                int currentItem = viewpager.getCurrentItem();                if(i != currentItem)                viewpager.setCurrentItem(i);            }            @Override            public void onNothingSelected(AdapterView<?> adapterView) {            }        });    }
然后,自定义一个ZoomImageView,继承ImageView,直接上代码了,代码里注释的挺详细
package com.hpl.demo_application;import android.annotation.TargetApi;import android.content.Context;import android.graphics.Matrix;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.os.Build;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;import android.view.ViewTreeObserver;import android.widget.ImageView;/** * 可缩放ImageView * Created by 79115 on 2016/12/1. */public class ZoomImageView2 extends ImageView implements ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener {    private final ScaleGestureDetector scaleGestureDetector;    private Matrix scaleMatrix = new Matrix();    private final float MAX_SCALE = 4.0f;    private float initScale = 1.0f;    private final float[] values = new float[9];    private boolean once = true;    public ZoomImageView2(Context context) {        this(context, null);    }    public ZoomImageView2(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ZoomImageView2(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //设置图片的缩放模式为矩形显示        setScaleType(ScaleType.MATRIX);        //创建ScaleGestureDetector实例        scaleGestureDetector = new ScaleGestureDetector(context, this);        //设置图片的触摸监听        this.setOnTouchListener(this);    }    @Override    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {        //此次放大的倍数        float scaleFactor = scaleGestureDetector.getScaleFactor();        //已经放大到的倍数        float scale = getScale();        if(getDrawable() == null){            return true;        }        if((scale < MAX_SCALE && scaleFactor > 1.0f)  //小于最大放大倍数并且放大                || (scale > initScale && scaleFactor < 1.0f)){ //大于最小倍数并且缩小            //放大后超过放大倍数,做处理            if(scale * scaleFactor > MAX_SCALE){                scaleFactor = MAX_SCALE / scale;            }            if(scale * scaleFactor < initScale){                scaleFactor = initScale / scale;            }            //以缩放手势的中心点缩放            scaleMatrix.postScale(scaleFactor, scaleFactor, scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY());            //检查边缘,当图片边缘放大后再缩小会仅有一部分显示在屏幕上,这时候需要将图片移到屏幕的中间来;            checkBorder();            setImageMatrix(scaleMatrix);        }        return true;    }    private void checkBorder() {        Matrix matrix = this.scaleMatrix;        RectF rectF = new RectF();        float dx = 0, dy = 0;        if(getDrawable() != null){            //设置范围            rectF.set(0, 0 ,getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());            matrix.mapRect(rectF);            
if(rectF.width() > getWidth()){    if (rectF.left > 0) {        dx = -rectF.left;    }    if (rectF.right < getWidth()) {       dx = getWidth() - rectF.right;    }}if (rectF.height() >= getHeight()) {    if (rectF.top > 0) {        dy = -rectF.top;    }    if (rectF.bottom < getHeight()) {        dy = getHeight() - rectF.bottom;    }}
// 如果宽或高小于屏幕,则让其居中 if (rectF.width() < getWidth()) { dx = -((rectF.right + rectF.left) / 2) + getWidth() / 2; } if (rectF.height() < getHeight()) { dy = -((rectF.top + rectF.bottom) / 2) + getHeight() / 2; } scaleMatrix.postTranslate(dx, dy); } } private float getScale() { scaleMatrix.getValues(values); return values[Matrix.MSCALE_X]; } @Override public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) { } @Override public boolean onTouch(View view, MotionEvent motionEvent) { //将触摸事件交给scaleGestureDetector处理 return scaleGestureDetector.onTouchEvent(motionEvent); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnGlobalLayoutListener(this); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeOnGlobalLayoutListener(this); } @Override public void onGlobalLayout() { if(once){ Drawable drawable = getDrawable(); if(drawable != null){ //获取控件的宽高 int width = getWidth(); int height = getHeight(); //获取图片的宽高 int dw = drawable.getIntrinsicWidth(); int dh = drawable.getIntrinsicHeight(); //如果图片的宽大于控件的宽,改变初始的缩放比例 if(dw > width && dh <= height){ initScale = width * 1.0f / dw; } //如果图片的高大于控件的高,改变初始的缩放比例 if(dh > height && dw <= width){ initScale = height * 1.0f / dh; } //如果图片的宽高都大于控件的宽高,则取其中比例小的,这样才能将图片显示完全 if(dh > height && dw > width){ initScale = Math.min((width * 1.0f) / dw, (height * 1.0f) / dh); } //将图片移到屏幕中间 scaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2); //按初始比例以控件中心为原点缩放图片 scaleMatrix.postScale(initScale, initScale, width / 2, height / 2); setImageMatrix(scaleMatrix); } once = false; } }}
将ViewPager构造器里的ImageView替换一下, 效果图如下,截图工具搞了老久,随便截取一下就挺大的,只能草草了事
可以看到这样来我们的图片已经有可缩放能力,但不能够拖动
下面我们开始做屏幕的拖动
@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {    //将触摸事件交给scaleGestureDetector处理    scaleGestureDetector.onTouchEvent(motionEvent);    if(getDrawable() == null){        return  true;    }    switch (motionEvent.getAction()){        case MotionEvent.ACTION_DOWN:            startX = motionEvent.getX();            startY = motionEvent.getY();            break;        case MotionEvent.ACTION_MOVE:            float x = motionEvent.getX();            float y = motionEvent.getY();            float dx = x - startX;            float dy = y - startY;            scaleMatrix.postTranslate(dx, dy);            checkBorder();            setImageMatrix(scaleMatrix);            startX = x;            startY = y;            break;        case MotionEvent.ACTION_UP:            break;    }    return true;}
这里整个图片浏览器基本上算是完成了,但是还得解决一个冲突问题,那就是viewpager的滑动事件和图片的拖动事件的冲突。大家微信什么的用的应该不少,可以发现多数图片预览器是只有当你的图片小于屏幕的时候你才能左右的切换屏幕,所以我们可以在onTouch里面加上这样的判断;
Matrix matrix = this.scaleMatrix;RectF rectF = new RectF();    //设置范围rectF.set(0, 0 ,getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight()); if(rectF.width() > getWidth() || rectF.height() > getHeight()){    //请求父类不拦截事件    getParent().requestDisallowInterceptTouchEvent(true);}
这样冲突就解决了,下面来波福利
好险,差点超过2M了
0 0