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

使用Android ViewPager与PhotoView实现图片滑动查看

2016-01-03 17:02 836 查看
安卓新手,最近在写一个小的个人项目,其中需要全屏查看一组网络图片。其实就是简单的图片查看功能。在网上搜了实现方法,最终在Github上找到了一个叫做Touch Gallery的项目,它不仅能够载入本地图片,还能载入网络图片,完全符合我的需求。可惜这个项目年代久远,作者也已经不再维护,加之我在将这个Eclipse平台编译的项目导入到Android Studio中时遇到了一些麻烦。遂决定另寻它法。

这里主要还是用到了Android自带的ViewPager控件,用于实现水平切换,并且它自带了滑动效果。将每一张需要展示的图片放在独立的Fragment中,ViewPager每滑动一次,展示新的Fragment。

1.设计Fragment的布局

<?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">
    <ImageView
        android:id="@+id/iv_main_pic"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerVertical="true"
        />
</LinearLayout>


Fragment的布局十分简单,只包含一个ImageView,它用来显示需要展示的图片。

2.建立自定义的PictureSlideFragment类继承自Fragment

由于每一个Fragment展示的图片不同,因此需要在创建PictureSlideFragment时传入需要加载的图片url。添加静态方法newInstance()获得一个包含图片url的PictureSlideFragmen的实例。接着在其执行onCreate()方法时,对url赋值,接着就能在onCreateView()方法中通过findViewById()找到ImageView的实例,并将其图片来源设置为指定的url.这里使用强大的Glide工具为ImageView加载网络图片。Glide的load()方法有很多重载,可以直接传入drawable的ResourceId加载本地图片,也可以传入url加载网络图片。此时,Fragment中显示的ImageView还是静态的,它不可移动,不可缩放,显然不符合查看高清大图时的需求。因此在使用Glide为ImageView填充图片之前,我们使用PhotoViewAttacher为图片添加支持缩放、平移的属性。至此,应该能符合我们的要求了,但是由于使用了PhotoViewAttacher,它有一个特性,就是在图片填充完毕后,需要调用update()方法。由于Glide加载网络图片的方式是异步的,因此Glide的into()方法中不能简单地传入需要填充的ImageView了,而是需要传入一个基于imageView的GlideDrawableImageViewTarget对象,并重写它的onResourceReady()方法,在该方法中调用PhotoViewAttacher的update()方法,使图片重新适配布局。注意,如果只是单纯地在Glide填充ImageView之后再调用上述update()方法,将会出现图片显示错位的情况。一开始我以为这是PhotoViewAttacher运用到ViewPager中的bug,困扰许久后我终于解决了这个小问题。

public class PictureSlideFragment extends Fragment {
    private String url;
    private PhotoViewAttacher mAttacher;
    private ImageView imageView;

    public static PictureSlideFragment newInstance(String url) {
        PictureSlideFragment f = new PictureSlideFragment();

        Bundle args = new Bundle();
        args.putString("url", url);
        f.setArguments(args);

        return f;<span style="white-space:pre">	</span>//获得一个包含图片url的PictureSlideFragmen的实例
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        url = getArguments() != null ? getArguments().getString("url") : "http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_6.jpg";

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v=inflater.inflate(R.layout.fragment_picture_slide,container,false);

        imageView= (ImageView) v.findViewById(R.id.iv_main_pic);
        mAttacher = new PhotoViewAttacher(imageView);//使用PhotoViewAttacher为图片添加支持缩放、平移的属性

        Glide.with(getActivity()).load(url).crossFade().into(new GlideDrawableImageViewTarget(imageView) {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
                super.onResourceReady(resource, animation);
                mAttacher.update();//调用PhotoViewAttacher的update()方法,使图片重新适配布局
            }
        });
        return v;
    }
}
3.定义PicViewerActivity布局

至此,单个Fragment就算设计好了。现在需要设计装载这些Fragment的Activity。它的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000">
    <TextView
        android:id="@+id/tv_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:textSize="30sp"
        android:textColor="#ffffff"
        />
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/tv_indicator"
        />
</RelativeLayout>
同样十分简单,它只包含了一个ViewPager与一个简单的TextView,后者用于显示当前页数以及总页数。

4.定义一个PicViewerActivity完成页面滑动显示的逻辑

首先定义PictureSlidePagerAdapter继承自FragmentStatePagerAdapter,并重写它的getItem()方法,它返回的是一个Fragment对象,这里我们返回的是展示不同网络图片的PictureSlideFragment。getCount()方法用于指定ViewPager的总页数,这里我们返回url地址的总个数。

接着,我们在Activity的onCreate()方法中获得ViewPager的实例,并为它指定一个PictureSlidePagerAdapter适配器。至此,已经实现了左右滑动页面,加载网络图片的基本功能了。最后我们为ViewPager设定页面滑动的监听器OnPageChangeListener,重写它的onPageScrolled()方法,在当前页面滑动至其他页面后,获取position值,并将其显示到TextView构成的简易页面指示器上。

/**Simple TouchGallery demo based on ViewPager and Photoview.
 * Created by Trojx on 2016/1/3.
 */
public class PicViewerActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private TextView tv_indicator;
    private ArrayList<String> urlList;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pic_viewer);

        String [] urls={"http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_0.jpg",
                "http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_1.jpg",
                "http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_2.jpg",
                "http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_3.jpg",
                "http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_4.jpg",
                "http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_5.jpg",
                "http://www.zhagame.com/wp-content/uploads/2016/01/JarvanIV_6.jpg",};//需要加载的网络图片

        urlList = new ArrayList<>();
        Collections.addAll(urlList, urls);

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        tv_indicator = (TextView) findViewById(R.id.tv_indicator);

        viewPager.setAdapter(new PictureSlidePagerAdapter(getSupportFragmentManager()));
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                tv_indicator.setText(String.valueOf(position+1)+"/"+urlList.size());//<span style="white-space: pre;">在当前页面滑动至其他页面后,获取position值</span>
            }

            @Override
            public void onPageSelected(int position) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

    }
    private  class PictureSlidePagerAdapter extends FragmentStatePagerAdapter{

        public PictureSlidePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return PictureSlideFragment.newInstance(urlList.get(position));//<span style="white-space: pre;">返回展示不同网络图片的PictureSlideFragment</span>
        }

        @Override
        public int getCount() {
            return urlList.size();//<span style="white-space: pre;">指定ViewPager的总页数</span>
        }
    }
}


我把这个简单功能的实现单独做成了一个小Demo,以备以后参考使用。完整代码在此处,项目地址:MyTouchGallery

以下是运行展示:



参考文章:

1.使用ViewPager实现图片滑动展示 http://blog.csdn.net/liujianjun_1985/article/details/40114393
2.glide的配置 http://blog.csdn.net/lijinhua7602/article/details/45624157
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: