在实际的开发中,我们市场会遇到这样的情况:点击某图片,浏览某列表(某列表详情)中的所有图片数据,当然,这些图片是可以放大和缩小的,比如我们看下百度贴吧的浏览大图的效果:

 链接

这种功能,在一些app中是必不可少的!那如何实现呢?接下来,我将介绍通过ViewPager结合PhotoView开源组件,实现这么样的经典效果!

关于ViewPager如何使用,此文不多介绍,网络上太多相关的知识了;而PhotoView,因为它是一个开源的组件,所以如果你不深入研究它的话,只需要掌握它基本的用法即可!

何为PhotoView?

PhotoView的github地址: https://github.com/chrisbanes/PhotoView

PhotoView特性:

    支持单点/多点触摸,即时缩放图片;

    支持平滑滚动;

    在滑动父控件下能够运行良好;(例如:ViewPager)

当用户的触点改变时可以触发通知。

关于如何PhotoView的详解,且参考如下文章:PhotoView开源项目剖析

当你了解了基本的知识后,下面直接带你进入实例:

1. 先定义网络请求,实现图片列表:

1.1 列表样式

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6.  
  7. <ImageView
  8. android:id="@+id/picBig"
  9. android:layout_width="fill_parent"
  10. android:layout_height="180dp"
  11. android:scaleType="fitXY"
  12. android:src="@mipmap/ic_launcher"
  13. />
  14. <TextView
  15. android:id="@+id/name"
  16. android:layout_width="fill_parent"
  17. android:layout_height="wrap_content"
  18. android:text="CSS动画实用技巧"
  19. android:singleLine="true"
  20. android:padding="10dp"
  21. android:textSize="15sp"
  22. />
  23.  
  24. <TextView
  25. android:id="@+id/description"
  26. android:layout_width="fill_parent"
  27. android:layout_height="wrap_content"
  28. android:text="教你使用CSS实现惊艳的动画效果!"
  29. android:textSize="12sp"
  30. android:lines="2"
  31. android:padding="10dp"
  32. />
  33.  
  34. </LinearLayout>

1.2 适配器

  1. public class KechengAdapter extends BaseAdapter {
  2.  
  3. private Context mContext;
  4.  
  5. private LayoutInflater mInflater;
  6.  
  7. private List<KeCheng> mDatas;
  8.  
  9. private OnImgClickListener onImgClickListener;
  10.  
  11. public void setOnImgClickListener(OnImgClickListener onImgClickListener){
  12. this.onImgClickListener = onImgClickListener;
  13. }
  14.  
  15. public KechengAdapter(Context context, List<KeCheng> datas) {
  16. mContext = context;
  17. mInflater = LayoutInflater.from(mContext);
  18. mDatas = datas;
  19. }
  20.  
  21. @Override
  22. public int getCount() {
  23. return (mDatas != null ? mDatas.size() : 0);
  24. }
  25.  
  26. @Override
  27. public Object getItem(int position) {
  28. return (mDatas != null ? mDatas.get(position) : null);
  29. }
  30.  
  31. @Override
  32. public long getItemId(int position) {
  33. return position;
  34. }
  35.  
  36. @Override
  37. public View getView(final int position, View convertView, ViewGroup parent) {
  38. ViewHolder holder = null;
  39. if (convertView == null) {
  40.  
  41. convertView = mInflater.inflate(R.layout.list_item_kecheng, null);
  42.  
  43. holder = new ViewHolder();
  44. holder.picBig = (ImageView) convertView.findViewById(R.id.picBig);
  45. holder.name = (TextView) convertView.findViewById(R.id.name);
  46. holder.description = (TextView) convertView.findViewById(R.id.description);
  47.  
  48. convertView.setTag(holder);
  49.  
  50. } else {
  51. holder = (ViewHolder) convertView.getTag();
  52. }
  53.  
  54. final KeCheng keCheng = mDatas.get(position);
  55.  
  56. if (keCheng != null) {
  57.  
  58. ImageLoaderUtil.getInstance().displayListItemImage(keCheng.picBig, holder.picBig);
  59.  
  60. holder.name.setText(keCheng.name);
  61. holder.description.setText(keCheng.description);
  62.  
  63. holder.picBig.setOnClickListener(new View.OnClickListener() {
  64. @Override
  65. public void onClick(View v) {
  66. onImgClickListener.handleBrowse(position);
  67. }
  68. });
  69.  
  70. }
  71. return convertView;
  72. }
  73.  
  74. public interface OnImgClickListener{
  75.  
  76. void handleBrowse(int position);
  77. }
  78.  
  79. static class ViewHolder {
  80.  
  81. ImageView picBig;
  82.  
  83. TextView name;
  84.  
  85. TextView description;
  86. }
  87. }

注; Adapter中主要添加了一个回调接口,当你单机图片的时候,进入下一级图片浏览页面!

2. 列表逻辑实现,及点击某一个图片,进入下一级页面,该页面即为图片浏览页面:

  1. public class MainActivity extends Activity implements KechengAdapter.OnImgClickListener {
  2.  
  3. private String BASE_URL = "http://www.imooc.com/api/teacher?type=4&num=10";
  4.  
  5. @ViewInject(R.id.main_layout)
  6. private RelativeLayout main_layout;
  7.  
  8. @ViewInject(R.id.list_kecheng)
  9. private ListView listKecheng;
  10.  
  11. private List<KeCheng> cks;
  12.  
  13. private KechengAdapter mAdapter;
  14.  
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  19.  
  20. setContentView(R.layout.activity_main);
  21.  
  22. ViewUtils.inject(this);
  23.  
  24. getDataFromServer();
  25. }
  26.  
  27. /**
  28. * 获取网络数据
  29. */
  30. private void getDataFromServer() {
  31.  
  32. HttpUtils http = new HttpUtils();
  33.  
  34. http.configCurrentHttpCacheExpiry(1000 * 5);
  35. // 设置超时时间
  36. http.configTimeout(5 * 1000);
  37. http.configSoTimeout(5 * 1000);
  38.  
  39. http.send(HttpRequest.HttpMethod.GET, BASE_URL, null, new RequestCallBack<String>() {
  40.  
  41. @Override
  42. public void onSuccess(ResponseInfo<String> responseInfo) {
  43.  
  44. Gson gson = new Gson();
  45. RspData rspData = gson.fromJson(responseInfo.result, RspData.class);
  46. cks = rspData.data;
  47.  
  48. if (mAdapter == null) {
  49.  
  50. mAdapter = new KechengAdapter(MainActivity.this, cks);
  51. listKecheng.setAdapter(mAdapter);
  52.  
  53. mAdapter.setOnImgClickListener(MainActivity.this);
  54.  
  55. } else {
  56. mAdapter.notifyDataSetChanged();
  57. }
  58. }
  59.  
  60. @Override
  61. public void onFailure(HttpException e, String s) {
  62.  
  63. }
  64. });
  65. }
  66.  
  67. @Override
  68. public void handleBrowse(int position) {
  69.  
  70. ArrayList<String> imgs = new ArrayList<>();
  71.  
  72. for (KeCheng data : cks) {
  73.  
  74. imgs.add(data.picBig);
  75. }
  76.  
  77. Intent intent = new Intent(this, ImageBrowseActivity.class);
  78. intent.putExtra("position", position);
  79. intent.putStringArrayListExtra("imgs", imgs);
  80. startActivity(intent);
  81.  
  82. }
  83. }

3. 图片浏览页面,使用ViewPager实现突破浏览:

3.1 ViewPager定义

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#ffffff"
  6. android:orientation="vertical">
  7.  
  8. <android.support.v4.view.ViewPager
  9. android:id="@+id/imgs_viewpager"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:layout_gravity="center" />
  13.  
  14. <ImageView
  15. android:id="@+id/img_browse_back"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:layout_marginLeft="5dp"
  19. android:layout_marginTop="25dp"
  20. android:padding="5dp"
  21. android:onClick="onBack"
  22. android:src="@mipmap/img_browse_back" />
  23.  
  24. </FrameLayout>

注: ViewPager为图片滑动浏览容器,ImageView为返回按钮(返回到上一级页面)

3.2 ViewPager逻辑实现:

  1. public class ImageBrowseActivity extends Activity {
  2.  
  3. private ViewPager search_viewpager;
  4.  
  5. private List<String> imgs;
  6.  
  7. private int position;
  8.  
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12.  
  13. setContentView(R.layout.activity_image_browse);
  14.  
  15. this.position = getIntent().getIntExtra("position", 0);
  16.  
  17. this.imgs = getIntent().getStringArrayListExtra("imgs");
  18.  
  19. search_viewpager = (ViewPager) this.findViewById(R.id.imgs_viewpager);
  20. search_viewpager.setOffscreenPageLimit(2);
  21.  
  22. System.out.println("position:" + position);
  23. System.out.println("imgs :" + imgs.size());
  24.  
  25. PagerAdapter adapter = new MyViewPagerAdapter(this, imgs);
  26. search_viewpager.setAdapter(adapter);
  27. search_viewpager.setCurrentItem(position);
  28. }
  29.  
  30. public void onBack(View view) {
  31. finish();
  32. }
  33. }

注: 设置ViewPager基本信息,并通过viewPager.setCurrentItem来定义当前显示哪一个图片,(位置的信息由上一级页面传递过来);

3.3 在ViewPager适配器PagerAdapter中实现网络图片的加载浏览:

  1. public class MyViewPagerAdapter extends PagerAdapter {
  2.  
  3. List<String> imgs;
  4.  
  5. Context mContext;
  6.  
  7. public MyViewPagerAdapter(Context context, List<String> imgs) {
  8.  
  9. this.mContext = context;
  10. this.imgs = imgs;
  11.  
  12. }
  13.  
  14. @Override
  15. public int getCount() { // 获得size
  16. return imgs.size();
  17. }
  18.  
  19. @Override
  20. public boolean isViewFromObject(View arg0, Object arg1) {
  21. return arg0 == arg1;
  22. }
  23.  
  24. @Override
  25. public void destroyItem(ViewGroup container, int position, Object object) {
  26. ((ViewPager) container).removeView((View) object);
  27. }
  28.  
  29. @Override
  30. public Object instantiateItem(ViewGroup container, int position) {
  31.  
  32. String imgUrl = imgs.get(position);
  33. LinearLayout view = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.img_browse, null);
  34. PhotoView img = (PhotoView) view.findViewById(R.id.img_plan);
  35. img.setTag(imgUrl);
  36. ImageLoaderUtil.getInstance().displayListItemImage(imgs.get(position), img);
  37.  
  38. ((ViewPager) container).addView(view);
  39.  
  40. return view;
  41.  
  42. }

注: 此处重点是两个方法,instantiateItem主要是加载View,在此处,通过ImageLoader加载网络图片;destroyItem中需要移除该View,避免View重复加载。

关于ImageLoader工具类,可以参考我之前的一篇博客:Android ListView性能优化实例讲解

基本上,通过以上方法,就可以实现网络图片在线浏览功能了,让我们看下效果吧:

后续: 本文主要介绍了通过PhotoView实现图片的缩放,放大缩小查看,其实还有一个开源项目GestureImageView,其github地址是:https://github.com/jasonpolites/gesture-imageview ,我也通过该开源项目实现了图片浏览,不过发现其效果并不如PhotoView那么好(主要表现在图片加载显示速度慢,不方面控制),代码会一起提供给大家参考。

源代码下载地址:https://github.com/zuiwuyuan/ImgsBrowse

Android 使用ViewPager结合PhotoView开源组件实现网络图片在线浏览功能的更多相关文章

  1. Android经常使用开源组件汇总

    http://www.cnblogs.com/scige/p/3456790.html UI相关 图片 Android-Universal-Image-Loader:com.nostra13.univ ...

  2. Android 开源组件 ----- Android LoopView无限自动轮转控件

    Android 开源组件 ----- Android LoopView无限自动轮转控件 2015-12-28 15:26 by 杰瑞教育, 32 阅读, 0 评论, 收藏, 编辑 一.组件介绍 App ...

  3. Android自定义控件 开源组件SlidingMenu的项目集成

    在实际项目开发中,定制一个菜单,能让用户得到更好的用户体验,诚然菜单的样式各种各样,但是有一种菜单——滑动菜单,是被众多应用广泛使用的.关于这种滑动菜单的实现,我在前面的博文中也介绍了如何自定义去实现 ...

  4. 支付宝 Android 版使用的开源组件

    支付宝 Android 版使用的开源组件 前言: 花了点时间整理了 支付宝 Android 客户端使用的开源组件,给需要的同学.在你不知道用什么开源框架的时候可以作下参考,毕竟支付宝是阿里的重量级产品 ...

  5. Android酷炫有用的开源框架

    一.代码库 1.from  代码家 整理比較好的源代码连接 一.兼容类库 ActionBarSherlock : Action Bar是Android 3.0后才開始支持的,ActionBarSher ...

  6. Android开发之经常使用开源库直接拿来用

    1.from  代码家 整理比較好的源代码连接 **************************************************************************** ...

  7. Android至ViewPager添加切换动画——使用属性动画

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/44200623 ViewPager作为Android最经常使用的的组件之中的一个.相 ...

  8. 011 Android TabLayout+ViewPager实现顶部滑动效果(多个页面)

    1.TabLayout介绍 TabLayout提供了一个水平的布局用来展示Tabs,很多应用都有这样的设计,典型的有网易新闻,简书,知乎等.TabLayout就可以很好的完成这一职责,首先TabLay ...

  9. Android酷炫实用的开源框架(UI框架)

    Android酷炫实用的开源框架(UI框架) 前言 忙碌的工作终于可以停息一段时间了,最近突然有一个想法,就是自己写一个app,所以找了一些合适开源控件,这样更加省时,再此分享给大家,希望能对大家有帮 ...

随机推荐

  1. ssh连接超时中断问题解决方案

    当在终端使用ssh命令连接到服务器时,如果一段时间没有活动连接会被中断,以下有两种方案可以解决: 一.修改ssh客户端配置 编辑客户端 /etc/ssh/ssh_config (或~/.ssh/con ...

  2. oracle-视图-索引-序列

    Oracle提高查询性能 一 视图 视图是一个虚拟表,就是对select查询的结果取个名字.其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值 ...

  3. 【模板】KMP [2017年5月计划 清北学堂51精英班Day2]

    Day2就搞一个KMP把  马拉车.AC自动机等准备省选的时候再说.. 模板题: 1204 寻找子串位置 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze     ...

  4. 洛谷P1002 过河卒 [2017年4月计划 动态规划15]

    P1002 过河卒 题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之 ...

  5. yield函数的执行顺序

    例子: 上图中标明了  行号出现的顺序 从顺序中可以看到 1.开始先执行for循环,执行到93行yield_test(1)时,会调用函数yield_test(),所以打印了79行内容 2.到80行时, ...

  6. 洛谷 2055 [ZJOI2009]假期的宿舍——二分图匹配

    题目:https://www.luogu.org/problemnew/show/P2055 #include<iostream> #include<cstdio> #incl ...

  7. 微信小程序--轮播图,标题,盒子,tab栏的合成例子

    小程序是什么? 微信小程序,是一种不需要下载安装即可使用的应用,用户扫一扫或搜一下即可打开应用,在微信-发现-小程序可打开应用. 一.小程序的样式编写: 目录结构: app.json { " ...

  8. Python结合OpenCV学习资料

    1.sunny2038的专栏  http://blog.csdn.net/sunny2038 作者建立了一个学习系列.讲得非常具体,有非常多的主要的图像处理实例. 2. https://github. ...

  9. vue 根据数组中某一项的值进行排序

    一.前言 我在vue项目中遇到了一个表格排序的需求,根据某一项的值的大小从大到小调整数组顺序. 二.代码 表格大概是这个样子,样式和图片在代码中简化了. <table class="r ...

  10. Hdu 4497

    题目链接 已知 gcd(x, y, z) = G, lcm(x, y, z) = L, 求有多少种组合(x, y, z)可以满足条件.G, L都在32位int范围内. 思路: 素数分解 + 容斥 L ...