Android仿微信朋友圈图片查看器

来源:互联网 发布:算法工程师老了怎么办 编辑:程序博客网 时间:2024/04/28 04:25

 转载请注明出处:http://blog.csdn.net/allen315410/article/details/40264551

        看博文之前,希望大家先打开自己的微信点到朋友圈中去,仔细观察是不是发现朋友圈里的有个“九宫格”的图片区域,点击图片又会跳到图片的详细查看页面,并且支持图片的滑动和缩放?这个功能是不是很常用呢?!那么我今天正好做了这个Demo,下面为大家讲解一下。首先按照惯例先看一下效果图吧,尤其不会录制gif动画(哎~没办法,模拟器不支持多点触控,刚好我的手机又没有Root,不能录屏,悲催啊,大家见谅,想要看真实效果的话,烦请移到博文最下方,点击下载源码,运行后再看效果哈~~),这里先就拿几张静态的图片顶替一下好了。见谅!

主页ListView的效果:                                  点击九宫格图片跳转到大图                                     多点触控,缩放图片

        

        效果嘛,将就着看吧!实在看不明白就想想微信朋友圈,或者拖到下方,点击下载源码!这里,首先分析一下主界面吧,布局都是很简单的,主界面仅仅就是一个ListView的控件,ListView的Item上值得注意的是,Item上包含了一个GridView,这个GridView呗用作实现“九宫格”的效果,主界面布局就是一个ListView,这里不说了,我们先来看看ListView的Item的布局吧,以下是item_list.xml

[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="5dp"  
  6.     android:paddingTop="5dp" >  
  7.   
  8.     <ImageView  
  9.         android:id="@+id/iv_avatar"  
  10.         android:layout_width="50dp"  
  11.         android:layout_height="50dp"  
  12.         android:background="@drawable/ic_launcher"  
  13.         android:scaleType="centerCrop" />  
  14.   
  15.     <TextView  
  16.         android:id="@+id/tv_title"  
  17.         android:layout_width="wrap_content"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_marginLeft="5dp"  
  20.         android:layout_toRightOf="@id/iv_avatar"  
  21.         android:text="爷,今天心情好!"  
  22.         android:textSize="16sp" />  
  23.   
  24.     <TextView  
  25.         android:id="@+id/tv_content"  
  26.         android:layout_width="wrap_content"  
  27.         android:layout_height="wrap_content"  
  28.         android:layout_below="@+id/tv_title"  
  29.         android:layout_marginLeft="5dp"  
  30.         android:layout_marginTop="3dp"  
  31.         android:layout_toRightOf="@id/iv_avatar"  
  32.         android:text="今天又是雾霾!"  
  33.         android:textSize="16sp" />  
  34.   
  35.     <com.example.imagedemo.NoScrollGridView  
  36.         android:id="@+id/gridview"  
  37.         android:layout_width="220dp"  
  38.         android:layout_height="wrap_content"  
  39.         android:layout_below="@id/tv_content"  
  40.         android:layout_marginLeft="5dp"  
  41.         android:layout_marginTop="3dp"  
  42.         android:layout_toRightOf="@id/iv_avatar"  
  43.         android:columnWidth="70dp"  
  44.         android:gravity="center"  
  45.         android:horizontalSpacing="2.5dp"  
  46.         android:numColumns="3"  
  47.         android:stretchMode="columnWidth"  
  48.         android:verticalSpacing="2.5dp" />  
  49.   
  50. </RelativeLayout>  

         好了,大家看到了,布局也是极其简单的,但是有个问题就是ListView嵌套进了GridView,那么就会出现一个问题,导致GridView显示的不全,那么该怎么解决这个问题呢?其实也简单,就是重写一个GridView,测量一下GridView的高度,再设置上去。具体解决方案请看上篇博文ListView嵌套GridView显示不全解决方法或者源码,如下NoScrollGridView.java

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. package com.example.imagedemo;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.widget.GridView;  
  6.   
  7. /** 
  8.  * 自定义的“九宫格”——用在显示帖子详情的图片集合 解决的问题:GridView显示不全,只显示了一行的图片,比较奇怪,尝试重写GridView来解决 
  9.  *  
  10.  * @author lichao 
  11.  * @since 2014-10-16 16:41 
  12.  *  
  13.  */  
  14. public class NoScrollGridView extends GridView {  
  15.   
  16.     public NoScrollGridView(Context context) {  
  17.         super(context);  
  18.         // TODO Auto-generated constructor stub  
  19.     }  
  20.   
  21.     public NoScrollGridView(Context context, AttributeSet attrs) {  
  22.         super(context, attrs);  
  23.         // TODO Auto-generated constructor stub  
  24.     }  
  25.   
  26.     public NoScrollGridView(Context context, AttributeSet attrs, int defStyle) {  
  27.         super(context, attrs, defStyle);  
  28.         // TODO Auto-generated constructor stub  
  29.     }  
  30.   
  31.     @Override  
  32.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  33.         // TODO Auto-generated method stub  
  34.         int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,  
  35.                 MeasureSpec.AT_MOST);  
  36.         super.onMeasure(widthMeasureSpec, expandSpec);  
  37.     }  
  38.   
  39. }  
        接下来看看ListView上面Item的实体是什么样的数据结构,这就显得非常简单了。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class ItemEntity {  
  2.     private String avatar; // 用户头像URL  
  3.     private String title; // 标题  
  4.     private String content; // 内容  
  5.     private ArrayList<String> imageUrls; // 九宫格图片的URL集合  
  6.   
  7.     public ItemEntity(String avatar, String title, String content,  
  8.             ArrayList<String> imageUrls) {  
  9.         super();  
  10.         this.avatar = avatar;  
  11.         this.title = title;  
  12.         this.content = content;  
  13.         this.imageUrls = imageUrls;  
  14.     }  
  15.        ...  
  16. }  

        好了,有了ListView,那么不可避免的就是做Item上的数据适配了。继承一个BaseAdapter,代码如下,都比较简单:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 首页ListView的数据适配器 
  3.  *  
  4.  * @author Administrator 
  5.  *  
  6.  */  
  7. public class ListItemAdapter extends BaseAdapter {  
  8.   
  9.     private Context mContext;  
  10.     private ArrayList<ItemEntity> items;  
  11.   
  12.     public ListItemAdapter(Context ctx, ArrayList<ItemEntity> items) {  
  13.         this.mContext = ctx;  
  14.         this.items = items;  
  15.     }  
  16.   
  17.     @Override  
  18.     public int getCount() {  
  19.         return items == null ? 0 : items.size();  
  20.     }  
  21.   
  22.     @Override  
  23.     public Object getItem(int position) {  
  24.         return items.get(position);  
  25.     }  
  26.   
  27.     @Override  
  28.     public long getItemId(int position) {  
  29.         return position;  
  30.     }  
  31.   
  32.     @Override  
  33.     public View getView(int position, View convertView, ViewGroup parent) {  
  34.         ViewHolder holder;  
  35.         if (convertView == null) {  
  36.             holder = new ViewHolder();  
  37.             convertView = View.inflate(mContext, R.layout.item_list, null);  
  38.             holder.iv_avatar = (ImageView) convertView  
  39.                     .findViewById(R.id.iv_avatar);  
  40.             holder.tv_title = (TextView) convertView  
  41.                     .findViewById(R.id.tv_title);  
  42.             holder.tv_content = (TextView) convertView  
  43.                     .findViewById(R.id.tv_content);  
  44.             holder.gridview = (NoScrollGridView) convertView  
  45.                     .findViewById(R.id.gridview);  
  46.             convertView.setTag(holder);  
  47.         } else {  
  48.             holder = (ViewHolder) convertView.getTag();  
  49.         }  
  50.         ItemEntity itemEntity = items.get(position);  
  51.         holder.tv_title.setText(itemEntity.getTitle());  
  52.         holder.tv_content.setText(itemEntity.getContent());  
  53.         // 使用ImageLoader加载网络图片  
  54.         DisplayImageOptions options = new DisplayImageOptions.Builder()//  
  55.                 .showImageOnLoading(R.drawable.ic_launcher) // 加载中显示的默认图片  
  56.                 .showImageOnFail(R.drawable.ic_launcher) // 设置加载失败的默认图片  
  57.                 .cacheInMemory(true// 内存缓存  
  58.                 .cacheOnDisk(true// sdcard缓存  
  59.                 .bitmapConfig(Config.RGB_565)// 设置最低配置  
  60.                 .build();//  
  61.         ImageLoader.getInstance().displayImage(itemEntity.getAvatar(),  
  62.                 holder.iv_avatar, options);  
  63.         final ArrayList<String> imageUrls = itemEntity.getImageUrls();  
  64.         if (imageUrls == null || imageUrls.size() == 0) { // 没有图片资源就隐藏GridView  
  65.             holder.gridview.setVisibility(View.GONE);  
  66.         } else {  
  67.             holder.gridview.setAdapter(new NoScrollGridAdapter(mContext,  
  68.                     imageUrls));  
  69.         }  
  70.         // 点击回帖九宫格,查看大图  
  71.         holder.gridview.setOnItemClickListener(new OnItemClickListener() {  
  72.   
  73.             @Override  
  74.             public void onItemClick(AdapterView<?> parent, View view,  
  75.                     int position, long id) {  
  76.                 // TODO Auto-generated method stub  
  77.                 imageBrower(position, imageUrls);  
  78.             }  
  79.         });  
  80.         return convertView;  
  81.     }  
  82.   
  83.     /** 
  84.      * 打开图片查看器 
  85.      *  
  86.      * @param position 
  87.      * @param urls2 
  88.      */  
  89.     protected void imageBrower(int position, ArrayList<String> urls2) {  
  90.         Intent intent = new Intent(mContext, ImagePagerActivity.class);  
  91.         // 图片url,为了演示这里使用常量,一般从数据库中或网络中获取  
  92.         intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_URLS, urls2);  
  93.         intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_INDEX, position);  
  94.         mContext.startActivity(intent);  
  95.     }  
  96.   
  97.     /** 
  98.      * listview组件复用,防止“卡顿” 
  99.      *  
  100.      * @author Administrator 
  101.      *  
  102.      */  
  103.     class ViewHolder {  
  104.         private ImageView iv_avatar;  
  105.         private TextView tv_title;  
  106.         private TextView tv_content;  
  107.         private NoScrollGridView gridview;  
  108.     }  
  109. }  

        这里有需要解释的地方了,看看listview上的图片处理,由于图片都是从网络获取的,为了避免图片过多造成OOM,那么这里加载图片的时候必不可少的需要做内存优化,图片的优化方式有很多,我这里采取了最简单最直接得方式,使用了开源的ImageLoader这个图片加载框架,这个框架简直是太优秀了,减少了开发者一系列不必要而且时常会出现的麻烦,关于ImageLoader并不是本篇博文需要讲解的知识,关于ImageLoader,欢迎在GitHub主页上下载,地址是https://github.com/nostra13/Android-Universal-Image-Loader,既然使用了ImageLoader这个框架,就不得不在程序上做一些初始化的操作,首先需要自定义一个全局的上下文Application类,将ImageLoader的相关属性初始化上去,直接看代码好了,见名知意:MyApplication.java

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class MyApplication extends Application {  
  2.     @Override  
  3.     public void onCreate() {  
  4.         super.onCreate();  
  5.         DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() //  
  6.                 .showImageForEmptyUri(R.drawable.ic_launcher) //  
  7.                 .showImageOnFail(R.drawable.ic_launcher) //  
  8.                 .cacheInMemory(true//  
  9.                 .cacheOnDisk(true//  
  10.                 .build();//  
  11.         ImageLoaderConfiguration config = new ImageLoaderConfiguration//  
  12.         .Builder(getApplicationContext())//  
  13.                 .defaultDisplayImageOptions(defaultOptions)//  
  14.                 .discCacheSize(50 * 1024 * 1024)//  
  15.                 .discCacheFileCount(100)// 缓存一百张图片  
  16.                 .writeDebugLogs()//  
  17.                 .build();//  
  18.         ImageLoader.getInstance().init(config);  
  19.     }  
  20. }  
       定义这个Application之后,需要在清单文件中配置一下,在Manifest.xml中的Application节点上添加:

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. android:name="com.example.imagedemo.MyApplication"  

        此外由于ImageLoader是网络获取图片,又需要本地sdcard缓存图片,所以需要加上一下的权限,这是Imageloader标准权限:

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <uses-permission android:name="android.permission.INTERNET" />  
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  3. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
       再看看上面的Item上数据,里面有个GridView,显然这个GridView也是需要做数据适配的,这个数据反应的是从网络加载图片,比较简单,看代码NoScrollGridAdapter.java

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1.      ......  
  2. Override  
  3. public View getView(int position, View convertView, ViewGroup parent) {  
  4.     View view = View.inflate(ctx, R.layout.item_gridview, null);  
  5.     ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);  
  6.     DisplayImageOptions options = new DisplayImageOptions.Builder()//  
  7.             .cacheInMemory(true)//  
  8.             .cacheOnDisk(true)//  
  9.             .bitmapConfig(Config.RGB_565)//  
  10.             .build();  
  11.     ImageLoader.getInstance().displayImage(imageUrls.get(position),  
  12.             imageView, options);  
  13.     return view;  
  14. }  
  15.     ......  
         这样,所有的数据适配就做好了,接下来就需要做图片查看器了,当我们点击ListView上Item里的“九宫格”——NoScrollGridView的某张图片的时候,需要把这个图片的url传给一个图片查看器,图片查看器里会根据传递进来的url去网络加载这张图片,那么其实图片查看器就是一个新的单独的Activity,这个Activity会包含一个ViewPager,用来管理多张图片的查看。image_detail_pager.xml

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  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.   
  6.     <com.example.imagedemo.HackyViewPager  
  7.         android:id="@+id/pager"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:background="@android:color/black" />  
  11.   
  12.     <TextView  
  13.         android:id="@+id/indicator"  
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:layout_gravity="bottom"  
  17.         android:background="@android:color/transparent"  
  18.         android:gravity="center"  
  19.         android:text="@string/viewpager_indicator"  
  20.         android:textColor="@android:color/white"  
  21.         android:textSize="18sp" />  
  22.   
  23. </FrameLayout>  
HackyViewPager.java
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class HackyViewPager extends ViewPager {  
  2.   
  3.     private static final String TAG = "HackyViewPager";  
  4.   
  5.     public HackyViewPager(Context context) {  
  6.         super(context);  
  7.     }  
  8.   
  9.     public HackyViewPager(Context context, AttributeSet attrs) {  
  10.         super(context, attrs);  
  11.     }  
  12.   
  13.     @Override  
  14.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  15.         try {  
  16.             return super.onInterceptTouchEvent(ev);  
  17.         } catch (IllegalArgumentException e) {  
  18.             // 不理会  
  19.             Log.e(TAG, "hacky viewpager error1");  
  20.             return false;  
  21.         } catch (ArrayIndexOutOfBoundsException e) {  
  22.             // 不理会  
  23.             Log.e(TAG, "hacky viewpager error2");  
  24.             return false;  
  25.         }  
  26.     }  
  27.   
  28. }  
ImagePagerActivity.java
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 图片查看器 
  3.  */  
  4. public class ImagePagerActivity extends FragmentActivity {  
  5.     private static final String STATE_POSITION = "STATE_POSITION";  
  6.     public static final String EXTRA_IMAGE_INDEX = "image_index";  
  7.     public static final String EXTRA_IMAGE_URLS = "image_urls";  
  8.   
  9.     private HackyViewPager mPager;  
  10.     private int pagerPosition;  
  11.     private TextView indicator;  
  12.   
  13.     @Override  
  14.     public void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.image_detail_pager);  
  17.   
  18.         pagerPosition = getIntent().getIntExtra(EXTRA_IMAGE_INDEX, 0);  
  19.         ArrayList<String> urls = getIntent().getStringArrayListExtra(  
  20.                 EXTRA_IMAGE_URLS);  
  21.   
  22.         mPager = (HackyViewPager) findViewById(R.id.pager);  
  23.         ImagePagerAdapter mAdapter = new ImagePagerAdapter(  
  24.                 getSupportFragmentManager(), urls);  
  25.         mPager.setAdapter(mAdapter);  
  26.         indicator = (TextView) findViewById(R.id.indicator);  
  27.   
  28.         CharSequence text = getString(R.string.viewpager_indicator, 1, mPager  
  29.                 .getAdapter().getCount());  
  30.         indicator.setText(text);  
  31.         // 更新下标  
  32.         mPager.setOnPageChangeListener(new OnPageChangeListener() {  
  33.   
  34.             @Override  
  35.             public void onPageScrollStateChanged(int arg0) {  
  36.             }  
  37.   
  38.             @Override  
  39.             public void onPageScrolled(int arg0, float arg1, int arg2) {  
  40.             }  
  41.   
  42.             @Override  
  43.             public void onPageSelected(int arg0) {  
  44.                 CharSequence text = getString(R.string.viewpager_indicator,  
  45.                         arg0 + 1, mPager.getAdapter().getCount());  
  46.                 indicator.setText(text);  
  47.             }  
  48.   
  49.         });  
  50.         if (savedInstanceState != null) {  
  51.             pagerPosition = savedInstanceState.getInt(STATE_POSITION);  
  52.         }  
  53.   
  54.         mPager.setCurrentItem(pagerPosition);  
  55.     }  
  56.   
  57.     @Override  
  58.     public void onSaveInstanceState(Bundle outState) {  
  59.         outState.putInt(STATE_POSITION, mPager.getCurrentItem());  
  60.     }  
  61.   
  62.     private class ImagePagerAdapter extends FragmentStatePagerAdapter {  
  63.   
  64.         public ArrayList<String> fileList;  
  65.   
  66.         public ImagePagerAdapter(FragmentManager fm, ArrayList<String> fileList) {  
  67.             super(fm);  
  68.             this.fileList = fileList;  
  69.         }  
  70.   
  71.         @Override  
  72.         public int getCount() {  
  73.             return fileList == null ? 0 : fileList.size();  
  74.         }  
  75.   
  76.         @Override  
  77.         public Fragment getItem(int position) {  
  78.             String url = fileList.get(position);  
  79.             return ImageDetailFragment.newInstance(url);  
  80.         }  
  81.   
  82.     }  
  83. }  

          已知图片查看的界面是继承自FragmentActivity的,所以支持显示的界面必须需要Fragment来实现,那么就自定义个Frangment吧,用这个Fragment来从url中获取图片资源,显示图片。image_detail_fragment.xml

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  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="@android:color/black" >  
  6.   
  7.     <ImageView  
  8.         android:id="@+id/image"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent"  
  11.         android:adjustViewBounds="true"  
  12.         android:contentDescription="@string/app_name"  
  13.         android:scaleType="centerCrop" />  
  14.   
  15.     <ProgressBar  
  16.         android:id="@+id/loading"  
  17.         android:layout_width="wrap_content"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_gravity="center"  
  20.         android:visibility="gone" />  
  21.   
  22. </FrameLayout>  
ImageDetailFragment.java

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 单张图片显示Fragment 
  3.  */  
  4. public class ImageDetailFragment extends Fragment {  
  5.     private String mImageUrl;  
  6.     private ImageView mImageView;  
  7.     private ProgressBar progressBar;  
  8.     private PhotoViewAttacher mAttacher;  
  9.   
  10.     public static ImageDetailFragment newInstance(String imageUrl) {  
  11.         final ImageDetailFragment f = new ImageDetailFragment();  
  12.   
  13.         final Bundle args = new Bundle();  
  14.         args.putString("url", imageUrl);  
  15.         f.setArguments(args);  
  16.   
  17.         return f;  
  18.     }  
  19.   
  20.     @Override  
  21.     public void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         mImageUrl = getArguments() != null ? getArguments().getString("url")  
  24.                 : null;  
  25.     }  
  26.   
  27.     @Override  
  28.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  29.             Bundle savedInstanceState) {  
  30.         final View v = inflater.inflate(R.layout.image_detail_fragment,  
  31.                 container, false);  
  32.         mImageView = (ImageView) v.findViewById(R.id.image);  
  33.         mAttacher = new PhotoViewAttacher(mImageView);  
  34.   
  35.         mAttacher.setOnPhotoTapListener(new OnPhotoTapListener() {  
  36.   
  37.             @Override  
  38.             public void onPhotoTap(View arg0, float arg1, float arg2) {  
  39.                 getActivity().finish();  
  40.             }  
  41.         });  
  42.   
  43.         progressBar = (ProgressBar) v.findViewById(R.id.loading);  
  44.         return v;  
  45.     }  
  46.   
  47.     @Override  
  48.     public void onActivityCreated(Bundle savedInstanceState) {  
  49.         super.onActivityCreated(savedInstanceState);  
  50.   
  51.         ImageLoader.getInstance().displayImage(mImageUrl, mImageView,  
  52.                 new SimpleImageLoadingListener() {  
  53.                     @Override  
  54.                     public void onLoadingStarted(String imageUri, View view) {  
  55.                         progressBar.setVisibility(View.VISIBLE);  
  56.                     }  
  57.   
  58.                     @Override  
  59.                     public void onLoadingFailed(String imageUri, View view,  
  60.                             FailReason failReason) {  
  61.                         String message = null;  
  62.                         switch (failReason.getType()) {  
  63.                         case IO_ERROR:  
  64.                             message = "下载错误";  
  65.                             break;  
  66.                         case DECODING_ERROR:  
  67.                             message = "图片无法显示";  
  68.                             break;  
  69.                         case NETWORK_DENIED:  
  70.                             message = "网络有问题,无法下载";  
  71.                             break;  
  72.                         case OUT_OF_MEMORY:  
  73.                             message = "图片太大无法显示";  
  74.                             break;  
  75.                         case UNKNOWN:  
  76.                             message = "未知的错误";  
  77.                             break;  
  78.                         }  
  79.                         Toast.makeText(getActivity(), message,  
  80.                                 Toast.LENGTH_SHORT).show();  
  81.                         progressBar.setVisibility(View.GONE);  
  82.                     }  
  83.   
  84.                     @Override  
  85.                     public void onLoadingComplete(String imageUri, View view,  
  86.                             Bitmap loadedImage) {  
  87.                         progressBar.setVisibility(View.GONE);  
  88.                         mAttacher.update();  
  89.                     }  
  90.                 });  
  91.     }  
  92. }  

         写到这里,此篇博文也宣告结束了。需要提出的是,我这里的图片查看器实现的图片的缩放效果使用的是开源组件PhotoView,关于PhotoView的github项目地址在这里,https://github.com/chrisbanes/PhotoView 需要点进去这个项目的网址,去下载源码,将源码全部拷贝到项目中来,使用也是相当方便的,demo如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. ImageView mImageView;  
  2. PhotoViewAttacher mAttacher;  
  3.   
  4. @Override  
  5. public void onCreate(Bundle savedInstanceState) {  
  6.     super.onCreate(savedInstanceState);  
  7.     setContentView(R.layout.activity_main);  
  8.   
  9.     // Any implementation of ImageView can be used!  
  10.     mImageView = (ImageView) findViewById(R.id.iv_photo);  
  11.   
  12.     // Set the Drawable displayed  
  13.     Drawable bitmap = getResources().getDrawable(R.drawable.wallpaper);  
  14.     mImageView.setImageDrawable(bitmap);  
  15.   
  16.     // Attach a PhotoViewAttacher, which takes care of all of the zooming functionality.  
  17.     mAttacher = new PhotoViewAttacher(mImageView);  
  18. }  
  19.   
  20.   
  21. // If you later call mImageView.setImageDrawable/setImageBitmap/setImageResource/etc then you just need to call  
  22. attacher.update();  

         刚开始这个图片查看器是我自己自定义View来实现的,其实需要实现图片的手势识别+多点触控+缩放,是可以使用矩阵Matrix来实现的,只不过这样显得特别的麻烦不说,而且极易出现BUG,这对于某些“急功近利”的项目来说,是个不好的兆头。所以,我这里摒弃了我用Matrix自定义的效果,改用github大牛为我们写好的开源组件,这样效率就上去了,大家也可以用Matrix自己去实现一下图片的多点触摸缩放的效果,关于Matrix的学习,请参加我以前的博文,Android自定义控件——3D画廊和图像矩阵。其实关于android上的图片缩放真没什么其它的方式,唯一能使用的还是Matrix这个类,不信先来瞧瞧Github大牛写的开源组件PhotoView是怎么实现的,查看以下部分源码:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. // These are set so we don't keep allocating them on the heap  
  2.     private final Matrix mBaseMatrix = new Matrix();  
  3.     private final Matrix mDrawMatrix = new Matrix();  
  4.     private final Matrix mSuppMatrix = new Matrix();  
  5.     private final RectF mDisplayRect = new RectF();  
  6.     private final float[] mMatrixValues = new float[9];  
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.     * Set's the ImageView's ScaleType to Matrix. 
  3.     */  
  4.    private static void setImageViewScaleTypeMatrix(ImageView imageView) {  
  5.        /** 
  6.         * PhotoView sets it's own ScaleType to Matrix, then diverts all calls 
  7.         * setScaleType to this.setScaleType automatically. 
  8.         */  
  9.        if (null != imageView && !(imageView instanceof IPhotoView)) {  
  10.            if (!ScaleType.MATRIX.equals(imageView.getScaleType())) {  
  11.                imageView.setScaleType(ScaleType.MATRIX);  
  12.            }  
  13.        }  
  14.    }  
        以上只是PhotoView的部分源码,一目了然的发现它的实现也是基于Matrix的,时间与篇幅的局限性,大家需要更好的了解PhotoView的实现的话,就下载它的源码查看吧,要理解大神的想法是需要一些扎实的基础,关于PhotoView的具体实现细节,我也弄不太明白,可能是我对Matrix了解的不深刻吧,希望以后加强学习,也希望以后跟你们交流学习,共同进步!


源码请在这里下载

2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手被山药痒了怎么办 9个月宝宝不吃奶粉怎么办 八个月宝宝拉粑粑费劲怎么办? 两个月小孩不吃奶粉怎么办 两个月的小孩不吃奶粉怎么办 两个多月宝宝不吃奶怎么办 三个多月宝宝不爱吃奶怎么办 4个月宝宝不吃奶怎么办 5个月宝宝不爱吃奶怎么办 九个月宝宝一直流鼻涕怎么办 九个月宝宝一直咳嗽怎么办 宝宝3岁不爱喝水怎么办 1岁宝宝不肯喝水怎么办 三个月宝宝体检说严重缺钙怎么办 1岁半宝宝不吃药怎么办 1岁宝宝抗拒吃药怎么办 六个月宝宝不爱吃辅食怎么办 宝宝九个月了不爱吃辅食怎么办 八个月宝宝不喜欢吃辅食怎么办 小孩米粉吃多了怎么办 宝宝四个月了奶水不足怎么办 4个月奶水不足怎么办 孩子不吃奶粉母乳又不够怎么办 宝宝吃母乳上火了怎么办 5个月宝宝厌奶期怎么办 九个月宝宝不吃奶粉怎么办 第5个月奶不够吃怎么办 九个月的宝宝不吃奶粉怎么办 9个月宝宝不肯吃怎么办 11个月不吃辅食怎么办 4个月母乳不足怎么办 宝宝四个月奶不够怎么办 四个月宝宝奶不够吃怎么办 宝宝吃母乳偏瘦怎么办 宝宝吃母乳很瘦怎么办 8个月宝宝流汗太多怎么办 奶水多乳房胀疼怎么办 乳房胀奶奶水减少怎么办 宝宝五个月奶水不够吃怎么办 梦见鬼在梦里怎么办 宝宝晚上奶水不够吃怎么办