Android中利用PhotoView查看图片

思路:当我们响应一个点击事件的时候 ,弹出一个dialog,我们将这个dialog自定义为全屏背景为半透明,这样图片以外的地方就会变成半透明,达到了查看图片的效果。

好了,首先我们必须要做的一件事情就是在build.gradle中导入相应的依赖,否则有些类是无法使用的。

dependencies {
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.github.chrisbanes.photoview:library:+'
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
}

然后我们在values文件夹中的styles.xml文件中自定义一个dialog。

接着我们需要写一个给显示dialog的布局文件,我们命名为dialog_images_brower.xml,但是在此之前,我们需要重写ViewPager控件,因为ViewPager存在一个闪退的bug,我们将我们重写的控件命名为ShowImagesViewPager.java。

public class ShowImagesViewPager extends ViewPager {
    public ShowImagesViewPager(Context context) {
        this(context,null);
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        try {
            return super.onInterceptTouchEvent(ev);
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}

然后我们就可以开始写布局文件dialog_images_brower.xml了。

"http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:gravity="center_horizontal"
             android:orientation="vertical"
             android:paddingTop="@dimen/padding_small_5dp">
    <com.damon43.showimagesdialogdemo.component.ShowImagesViewPager
        android:id="@+id/vp_images"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="@dimen/padding_small_10dp"/>

当我们写好了布局文件后,我们需要使用它,那么我们就需要自己重写一个dialog类文件,我们创建ShowImagesDialog继承自Dialog,并且为ViewPager写一个适配器ShowImagesAdapter继承自PagerAdapter,将我们需要查看的图片适配进去。

public class ShowImagesDialog extends Dialog {

    private View mView ;
    private Context mContext;
    private ShowImagesViewPager mViewPager;
    private List mImgUrls;
    private List mViews;
    private ShowImagesAdapter mAdapter;

    public ShowImagesDialog(@NonNull Context context, List imgUrls) {
        super(context, R.style.transparentBgDialog);
        this.mContext = context;//传入上下文
        this.mImgUrls = imgUrls;//传入图片String数组
        initView();
        initData();
    }

    private void initView() {
        mView = View.inflate(mContext, R.layout.dialog_images_brower, null);//通过inflate()方法找到我们写好的包含ViewPager的布局文件
        mViewPager = (ShowImagesViewPager) mView.findViewById(R.id.vp_images);//找到ViewPager控件并且实例化
        mViews = new ArrayList<>();//创建一个控件的数组,我们可以在ViewPager中加入很多图片,滑动改变图片
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(mView);
        Window window = getWindow();
        WindowManager.LayoutParams wl = window.getAttributes();
        wl.x = 0;
        wl.y = 0;
        wl.height = Config.EXACT_SCREEN_HEIGHT;
        wl.width = Config.EXACT_SCREEN_WIDTH;
        wl.gravity = Gravity.CENTER;
        window.setAttributes(wl);
        //EXACT_SCREEN_HEIGHT,EXACT_SCREEN_WIDTH为自定义Config类中的静态变量
        //在MainActivity中会给这两个变量赋值,分别对应手机屏幕高度和宽度
        //在这里我们通过WindowManager.LayoutParams把当前dialog的大小设置为全屏
    }

    private void initData() {
        //当PhotoView被点击时,添加相应的点击事件
        PhotoViewAttacher.OnPhotoTapListener listener = new PhotoViewAttacher.OnPhotoTapListener() {
            @Override
            public void onPhotoTap(View view, float x, float y) {
                dismiss();//点击图片后,返回到原来的界面
            }
        };
        for (int i = 0; i < mImgUrls.size(); i++) {
            final PhotoView photoView = new uk.co.senab.photoview.PhotoView(mContext);
            //创建一个PhotoView对象
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            photoView.setLayoutParams(layoutParams);
            //我们通过ViewGroup.LayoutParams来设置子控件PhotoView的大小
            photoView.setOnPhotoTapListener(listener);//给PhotoView添加点击事件
            Glide.with(mContext)
                    .load(mImgUrls.get(i))//导入图片
                    .placeholder(R.mipmap.ic_launcher)//加载图片过程中显示的替代图片
                    .error(R.mipmap.ic_launcher)//图片加载失败时显示的图片
                    .into(new SimpleTarget() {
                        //这是Glide的一个回调方法
                        //我们首先定义了一个SimpleTarget,然后把它通过into方法传入。
                        // 这样当Glide去服务器请求图片成功之后,
                        // 它会把请求到的图片资源作为GlideDrawable传递回来,
                        // 你可以使用这个GlideDrawable进行自己想要的操作,
                @Override
                public void onResourceReady(GlideDrawable resource, GlideAnimationsuper GlideDrawable> glideAnimation) {
                    photoView.setImageDrawable(resource);
                    //我们把回调过来的图片资源加载到PhotoView中
                    //大家有没有发现一个细节,我在布局文件中并没有创建PhotoView控件,而是创建的ViewPager
                    //因为我们需要在ViewPager中加入多个PhotoView以达到图片翻页的功能
                    //因此我们在加载图片时,想要把图片加载到任意的图片控件中,就需要Glide回调方法
                }
            });
            mViews.add(photoView);//最后把我们加载的所有PhotoView传给View数组
        }

        mAdapter = new ShowImagesAdapter(mViews);//给适配器传入图片控件数组
        mViewPager.setAdapter(mAdapter);
        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            //给ViewPager添加监听事件
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

}

然后贴入我的适配器代码

public class ShowImagesAdapter extends PagerAdapter {

    private List views;

    public ShowImagesAdapter(List views) {
        this.views = views;
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
        //确定一个页面视图是否关联到一个特定的对象。
    }

    @Override
    public int getCount() {
        return views.size();
        //得到控件数组个数
    }

    //一般来说,destroyitem在viewpager移除一个item时调用。
    // viewpage一般都会缓冲3个item,即一开始就会调用3次instantiateItem,
    // 当向右滑动,到第3页时,第1页的item会被调用到destroyitem
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ((ViewPager) container).removeView(views.get(position));
    }
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ((ViewPager) container).addView(views.get(position));
        return views.get(position);
    }
}

好了,我们把自定义的dialog搞定了,接下来我们可以直接在MainActivity中使用了。由于我们封装性很强,因此使用方法很简单,直接new一个ShowImagesDialog类就行了~

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getDeviceDensity();
        final List urls = new ArrayList<>();
        urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1511198824138&di=cec97b6363a1bce28b8499a31b78df83&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farchive%2F3e282f8762696b0bbb3ed16a5dc193c718e5aff9.jpg");
        urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1511793592&di=08b8de22336028a68c9a0bbbe7a9066d&imgtype=jpg&er=1&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2F7ea7878cfbddb27bb8a23e2407bfa7a48655f317.jpg");
        urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1511198824136&di=f4dc71ffdbbb16d9e3d496cf8add5376&imgtype=0&src=http%3A%2F%2Foss.tan8.com%2Fresource%2Fattachment%2F2017%2F201707%2F962b7304d0adc7e2e1d374dc6786e302.jpg");
        findViewById(R.id.btn_show_imgs).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new ShowImagesDialog(MainActivity.this, urls).show();
            }
        });
    }

    /**
     * 获取当前设备的屏幕密度等基本参数
     */
    protected void getDeviceDensity() {
        DisplayMetrics metrics = new DisplayMetrics();//通过DisplayMetrics类可以得到手机屏幕的参数
        getWindowManager().getDefaultDisplay().getMetrics(metrics);//然后将DisplayMetrics对象传入
        Config.EXACT_SCREEN_HEIGHT = metrics.heightPixels;//得到手机屏幕的高的分辨率
        Config.EXACT_SCREEN_WIDTH = metrics.widthPixels;//得到手机屏幕宽的分辨率
    }
}

这是MainActivity的布局

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:padding="@dimen/padding_small_10dp"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_show_imgs"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="@dimen/padding_small_10dp"
        android:text="@string/clicktoshowimgs"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
FrameLayout>

是不是很简单,我们直接点击一个按钮,就可以查看我们从网络上获取的图片了。

Android中利用PhotoView查看图片_第1张图片
Android中利用PhotoView查看图片_第2张图片
Android中利用PhotoView查看图片_第3张图片

你可能感兴趣的:(一个程序员的爬坑之路)