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  

相关文章
|
29天前
|
数据库 Android开发 开发者
构建高效Android应用:采用Kotlin协程优化网络请求处理
【2月更文挑战第30天】 在移动应用开发领域,网络请求的处理是影响用户体验的关键环节。针对Android平台,利用Kotlin协程能够极大提升异步任务处理的效率和简洁性。本文将探讨如何通过Kotlin协程优化Android应用中的网络请求处理流程,包括协程的基本概念、网络请求的异步执行以及错误处理等方面,旨在帮助开发者构建更加流畅和响应迅速的Android应用。
|
1月前
|
XML 缓存 Android开发
Android开发,使用kotlin学习多媒体功能(详细)
Android开发,使用kotlin学习多媒体功能(详细)
96 0
|
2月前
|
设计模式 Android开发
[Android 四大组件] --- BroadcastReceiver
[Android 四大组件] --- BroadcastReceiver
33 0
|
3月前
|
Android开发 开发者
什么是Android Jetpack,它包括哪些组件?
什么是Android Jetpack,它包括哪些组件?
39 0
|
3月前
|
安全 API Android开发
Android网络和数据交互: 解释Retrofit库的作用。
Android网络和数据交互: 解释Retrofit库的作用。
38 0
|
3月前
|
安全 网络协议 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
29 0
|
3月前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
21 0
|
3天前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android&#39;s AsyncTask simplifies asynchronous tasks for brief background work, bridging UI and worker threads. It involves execute() for starting tasks, doInBackground() for background execution, publishProgress() for progress updates, and onPostExecute() for returning results to the main thread.
3 0
|
3天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
5 0
|
2月前
|
数据可视化 Android开发
[Android 四大组件] --- Service
[Android 四大组件] --- Service
24 0