Android 使用ViewPager结合PhotoView开源组件实现网络图片在线浏览功能

简介:

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

 链接


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

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

  何为PhotoView?

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

  PhotoView特性:
    支持单点/多点触摸,即时缩放图片;
    支持平滑滚动;
    在滑动父控件下能够运行良好;(例如:ViewPager)

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


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


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

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

 1.1 列表样式

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/picBig"
        android:layout_width="fill_parent"
        android:layout_height="180dp"
        android:scaleType="fitXY"
        android:src="@mipmap/ic_launcher"
        />
    <TextView
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="CSS动画实用技巧"
        android:singleLine="true"
        android:padding="10dp"
        android:textSize="15sp"
        />

    <TextView
        android:id="@+id/description"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="教你使用CSS实现惊艳的动画效果!"
        android:textSize="12sp"
        android:lines="2"
        android:padding="10dp"
        />

</LinearLayout>

 1.2 适配器

public class KechengAdapter extends BaseAdapter {

    private Context mContext;

    private LayoutInflater mInflater;

    private List<KeCheng> mDatas;

    private OnImgClickListener onImgClickListener;

    public void setOnImgClickListener(OnImgClickListener onImgClickListener){
        this.onImgClickListener = onImgClickListener;
    }

    public KechengAdapter(Context context, List<KeCheng> datas) {
        mContext = context;
        mInflater = LayoutInflater.from(mContext);
        mDatas = datas;
    }

    @Override
    public int getCount() {
        return (mDatas != null ? mDatas.size() : 0);
    }

    @Override
    public Object getItem(int position) {
        return (mDatas != null ? mDatas.get(position) : null);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {

            convertView = mInflater.inflate(R.layout.list_item_kecheng, null);

            holder = new ViewHolder();
            holder.picBig = (ImageView) convertView.findViewById(R.id.picBig);
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.description = (TextView) convertView.findViewById(R.id.description);

            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        final KeCheng keCheng = mDatas.get(position);

        if (keCheng != null) {

            ImageLoaderUtil.getInstance().displayListItemImage(keCheng.picBig, holder.picBig);

            holder.name.setText(keCheng.name);
            holder.description.setText(keCheng.description);

            holder.picBig.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onImgClickListener.handleBrowse(position);
                }
            });

        }
        return convertView;
    }

    public interface OnImgClickListener{

        void handleBrowse(int position);
    }

    static class ViewHolder {

        ImageView picBig;

        TextView name;

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

 


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

public class MainActivity extends Activity implements KechengAdapter.OnImgClickListener {

    private String BASE_URL = "http://www.imooc.com/api/teacher?type=4&num=10";

    @ViewInject(R.id.main_layout)
    private RelativeLayout main_layout;

    @ViewInject(R.id.list_kecheng)
    private ListView listKecheng;

    private List<KeCheng> cks;

    private KechengAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.activity_main);

        ViewUtils.inject(this);

        getDataFromServer();
    }

    /**
     * 获取网络数据
     */
    private void getDataFromServer() {

        HttpUtils http = new HttpUtils();

        http.configCurrentHttpCacheExpiry(1000 * 5);
        // 设置超时时间
        http.configTimeout(5 * 1000);
        http.configSoTimeout(5 * 1000);

        http.send(HttpRequest.HttpMethod.GET, BASE_URL, null, new RequestCallBack<String>() {

            @Override
            public void onSuccess(ResponseInfo<String> responseInfo) {

                Gson gson = new Gson();
                RspData rspData = gson.fromJson(responseInfo.result, RspData.class);
                cks = rspData.data;

                if (mAdapter == null) {

                    mAdapter = new KechengAdapter(MainActivity.this, cks);
                    listKecheng.setAdapter(mAdapter);

                    mAdapter.setOnImgClickListener(MainActivity.this);

                } else {
                    mAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onFailure(HttpException e, String s) {

            }
        });
    }

    @Override
    public void handleBrowse(int position) {

        ArrayList<String> imgs = new ArrayList<>();

        for (KeCheng data : cks) {

            imgs.add(data.picBig);
        }

        Intent intent = new Intent(this, ImageBrowseActivity.class);
        intent.putExtra("position", position);
        intent.putStringArrayListExtra("imgs", imgs);
        startActivity(intent);

    }
}


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

 3.1 ViewPager定义

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/imgs_viewpager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

    <ImageView
        android:id="@+id/img_browse_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="25dp"
        android:padding="5dp"
        android:onClick="onBack"
        android:src="@mipmap/img_browse_back" />

</FrameLayout>

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


 3.2 ViewPager逻辑实现:

public class ImageBrowseActivity extends Activity {

    private ViewPager search_viewpager;

    private List<String> imgs;

    private int position;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_image_browse);

        this.position = getIntent().getIntExtra("position", 0);

        this.imgs = getIntent().getStringArrayListExtra("imgs");

        search_viewpager = (ViewPager) this.findViewById(R.id.imgs_viewpager);
        search_viewpager.setOffscreenPageLimit(2);

        System.out.println("position:" + position);
        System.out.println("imgs :" + imgs.size());

        PagerAdapter adapter = new MyViewPagerAdapter(this, imgs);
        search_viewpager.setAdapter(adapter);
        search_viewpager.setCurrentItem(position);
    }

    public void onBack(View view) {
        finish();
    }
}

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


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

public class MyViewPagerAdapter extends PagerAdapter {

    List<String> imgs;

    Context mContext;

    public MyViewPagerAdapter(Context context, List<String> imgs) {

        this.mContext = context;
        this.imgs = imgs;

    }

    @Override
    public int getCount() { // 获得size
        return imgs.size();
    }

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

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ((ViewPager) container).removeView((View) object);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        String imgUrl = imgs.get(position);
        LinearLayout view = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.img_browse, null);
        PhotoView img = (PhotoView) view.findViewById(R.id.img_plan);
        img.setTag(imgUrl);
        ImageLoaderUtil.getInstance().displayListItemImage(imgs.get(position), img);

        ((ViewPager) container).addView(view);

        return view;

    }

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


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


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



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


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

相关文章
|
22天前
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
25天前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
58 0
|
27天前
|
网络协议 物联网 虚拟化
|
5天前
|
缓存 JavaScript
Vue加载网络组件(远程组件)
【10月更文挑战第23天】在 Vue 中实现加载网络组件(远程组件)可以通过多种方式来完成。
|
9天前
|
网络协议 Shell 网络安全
解决两个 Android 模拟器之间无法网络通信的问题
让同一个 PC 上运行的两个 Android 模拟器之间能相互通信,出(qiong)差(ren)的智慧。
15 3
|
25天前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
1月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
38 6
|
18天前
|
机器学习/深度学习 算法
神经网络的结构与功能
神经网络是一种广泛应用于机器学习和深度学习的模型,旨在模拟人类大脑的信息处理方式。它们由多层不同类型的节点或“神经元”组成,每层都有特定的功能和责任。
19 0
|
2月前
|
5G 网络安全 SDN
网络功能虚拟化(NFV)和软件定义网络(SDN):赋能5G网络灵活、智能演进的关键
网络功能虚拟化(NFV)和软件定义网络(SDN):赋能5G网络灵活、智能演进的关键
61 3
|
29天前
|
NoSQL 网络协议 应用服务中间件
redis,memcached,nginx网络组件
redis,memcached,nginx网络组件
15 0

热门文章

最新文章