转载 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 plain copy print ?
  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. <ImageView
  8. android:id="@+id/iv_avatar"
  9. android:layout_width="50dp"
  10. android:layout_height="50dp"
  11. android:background="@drawable/ic_launcher"
  12. android:scaleType="centerCrop" />
  13. <TextView
  14. android:id="@+id/tv_title"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:layout_marginLeft="5dp"
  18. android:layout_toRightOf="@id/iv_avatar"
  19. android:text="爷,今天心情好!"
  20. android:textSize="16sp" />
  21. <TextView
  22. android:id="@+id/tv_content"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:layout_below="@+id/tv_title"
  26. android:layout_marginLeft="5dp"
  27. android:layout_marginTop="3dp"
  28. android:layout_toRightOf="@id/iv_avatar"
  29. android:text="今天又是雾霾!"
  30. android:textSize="16sp" />
  31. <com.example.imagedemo.NoScrollGridView
  32. android:id="@+id/gridview"
  33. android:layout_width="220dp"
  34. android:layout_height="wrap_content"
  35. android:layout_below="@id/tv_content"
  36. android:layout_marginLeft="5dp"
  37. android:layout_marginTop="3dp"
  38. android:layout_toRightOf="@id/iv_avatar"
  39. android:columnWidth="70dp"
  40. android:gravity="center"
  41. android:horizontalSpacing="2.5dp"
  42. android:numColumns="3"
  43. android:stretchMode="columnWidth"
  44. android:verticalSpacing="2.5dp" />
  45. </RelativeLayout>

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

[java]  view plain copy print ?
  1. package com.example.imagedemo;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.widget.GridView;
  5. /**
  6. * 自定义的“九宫格”——用在显示帖子详情的图片集合 解决的问题:GridView显示不全,只显示了一行的图片,比较奇怪,尝试重写GridView来解决
  7. *
  8. * @author lichao
  9. * @since 2014-10-16 16:41
  10. *
  11. */
  12. public class NoScrollGridView extends GridView {
  13. public NoScrollGridView(Context context) {
  14. super(context);
  15. // TODO Auto-generated constructor stub
  16. }
  17. public NoScrollGridView(Context context, AttributeSet attrs) {
  18. super(context, attrs);
  19. // TODO Auto-generated constructor stub
  20. }
  21. public NoScrollGridView(Context context, AttributeSet attrs, int defStyle) {
  22. super(context, attrs, defStyle);
  23. // TODO Auto-generated constructor stub
  24. }
  25. @Override
  26. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  27. // TODO Auto-generated method stub
  28. int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
  29. MeasureSpec.AT_MOST);
  30. super.onMeasure(widthMeasureSpec, expandSpec);
  31. }
  32. }

接下来看看ListView上面Item的实体是什么样的数据结构,这就显得非常简单了。

[java]  view plain copy print ?
  1. public class ItemEntity {
  2. private String avatar; // 用户头像URL
  3. private String title; // 标题
  4. private String content; // 内容
  5. private ArrayList<String> imageUrls; // 九宫格图片的URL集合
  6. public ItemEntity(String avatar, String title, String content,
  7. ArrayList<String> imageUrls) {
  8. super();
  9. this.avatar = avatar;
  10. this.title = title;
  11. this.content = content;
  12. this.imageUrls = imageUrls;
  13. }
  14. ...
  15. }

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

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

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

[java]  view plain copy print ?
  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 plain copy print ?
  1. android:name="com.example.imagedemo.MyApplication"

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

[html]  view plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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. <com.example.imagedemo.HackyViewPager
  6. android:id="@+id/pager"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:background="@android:color/black" />
  10. <TextView
  11. android:id="@+id/indicator"
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"
  14. android:layout_gravity="bottom"
  15. android:background="@android:color/transparent"
  16. android:gravity="center"
  17. android:text="@string/viewpager_indicator"
  18. android:textColor="@android:color/white"
  19. android:textSize="18sp" />
  20. </FrameLayout>

HackyViewPager.java

[java]  view plain copy print ?
  1. public class HackyViewPager extends ViewPager {
  2. private static final String TAG = "HackyViewPager";
  3. public HackyViewPager(Context context) {
  4. super(context);
  5. }
  6. public HackyViewPager(Context context, AttributeSet attrs) {
  7. super(context, attrs);
  8. }
  9. @Override
  10. public boolean onInterceptTouchEvent(MotionEvent ev) {
  11. try {
  12. return super.onInterceptTouchEvent(ev);
  13. } catch (IllegalArgumentException e) {
  14. // 不理会
  15. Log.e(TAG, "hacky viewpager error1");
  16. return false;
  17. } catch (ArrayIndexOutOfBoundsException e) {
  18. // 不理会
  19. Log.e(TAG, "hacky viewpager error2");
  20. return false;
  21. }
  22. }
  23. }

ImagePagerActivity.java

[java]  view plain copy print ?
  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. private HackyViewPager mPager;
  9. private int pagerPosition;
  10. private TextView indicator;
  11. @Override
  12. public void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.image_detail_pager);
  15. pagerPosition = getIntent().getIntExtra(EXTRA_IMAGE_INDEX, 0);
  16. ArrayList<String> urls = getIntent().getStringArrayListExtra(
  17. EXTRA_IMAGE_URLS);
  18. mPager = (HackyViewPager) findViewById(R.id.pager);
  19. ImagePagerAdapter mAdapter = new ImagePagerAdapter(
  20. getSupportFragmentManager(), urls);
  21. mPager.setAdapter(mAdapter);
  22. indicator = (TextView) findViewById(R.id.indicator);
  23. CharSequence text = getString(R.string.viewpager_indicator, 1, mPager
  24. .getAdapter().getCount());
  25. indicator.setText(text);
  26. // 更新下标
  27. mPager.setOnPageChangeListener(new OnPageChangeListener() {
  28. @Override
  29. public void onPageScrollStateChanged(int arg0) {
  30. }
  31. @Override
  32. public void onPageScrolled(int arg0, float arg1, int arg2) {
  33. }
  34. @Override
  35. public void onPageSelected(int arg0) {
  36. CharSequence text = getString(R.string.viewpager_indicator,
  37. arg0 + 1, mPager.getAdapter().getCount());
  38. indicator.setText(text);
  39. }
  40. });
  41. if (savedInstanceState != null) {
  42. pagerPosition = savedInstanceState.getInt(STATE_POSITION);
  43. }
  44. mPager.setCurrentItem(pagerPosition);
  45. }
  46. @Override
  47. public void onSaveInstanceState(Bundle outState) {
  48. outState.putInt(STATE_POSITION, mPager.getCurrentItem());
  49. }
  50. private class ImagePagerAdapter extends FragmentStatePagerAdapter {
  51. public ArrayList<String> fileList;
  52. public ImagePagerAdapter(FragmentManager fm, ArrayList<String> fileList) {
  53. super(fm);
  54. this.fileList = fileList;
  55. }
  56. @Override
  57. public int getCount() {
  58. return fileList == null ? 0 : fileList.size();
  59. }
  60. @Override
  61. public Fragment getItem(int position) {
  62. String url = fileList.get(position);
  63. return ImageDetailFragment.newInstance(url);
  64. }
  65. }
  66. }

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

[html]  view plain copy print ?
  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. <ImageView
  7. android:id="@+id/image"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:adjustViewBounds="true"
  11. android:contentDescription="@string/app_name"
  12. android:scaleType="centerCrop" />
  13. <ProgressBar
  14. android:id="@+id/loading"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:layout_gravity="center"
  18. android:visibility="gone" />
  19. </FrameLayout>

ImageDetailFragment.java

[java]  view plain copy print ?
  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. public static ImageDetailFragment newInstance(String imageUrl) {
  10. final ImageDetailFragment f = new ImageDetailFragment();
  11. final Bundle args = new Bundle();
  12. args.putString("url", imageUrl);
  13. f.setArguments(args);
  14. return f;
  15. }
  16. @Override
  17. public void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19. mImageUrl = getArguments() != null ? getArguments().getString("url")
  20. : null;
  21. }
  22. @Override
  23. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  24. Bundle savedInstanceState) {
  25. final View v = inflater.inflate(R.layout.image_detail_fragment,
  26. container, false);
  27. mImageView = (ImageView) v.findViewById(R.id.image);
  28. mAttacher = new PhotoViewAttacher(mImageView);
  29. mAttacher.setOnPhotoTapListener(new OnPhotoTapListener() {
  30. @Override
  31. public void onPhotoTap(View arg0, float arg1, float arg2) {
  32. getActivity().finish();
  33. }
  34. });
  35. progressBar = (ProgressBar) v.findViewById(R.id.loading);
  36. return v;
  37. }
  38. @Override
  39. public void onActivityCreated(Bundle savedInstanceState) {
  40. super.onActivityCreated(savedInstanceState);
  41. ImageLoader.getInstance().displayImage(mImageUrl, mImageView,
  42. new SimpleImageLoadingListener() {
  43. @Override
  44. public void onLoadingStarted(String imageUri, View view) {
  45. progressBar.setVisibility(View.VISIBLE);
  46. }
  47. @Override
  48. public void onLoadingFailed(String imageUri, View view,
  49. FailReason failReason) {
  50. String message = null;
  51. switch (failReason.getType()) {
  52. case IO_ERROR:
  53. message = "下载错误";
  54. break;
  55. case DECODING_ERROR:
  56. message = "图片无法显示";
  57. break;
  58. case NETWORK_DENIED:
  59. message = "网络有问题,无法下载";
  60. break;
  61. case OUT_OF_MEMORY:
  62. message = "图片太大无法显示";
  63. break;
  64. case UNKNOWN:
  65. message = "未知的错误";
  66. break;
  67. }
  68. Toast.makeText(getActivity(), message,
  69. Toast.LENGTH_SHORT).show();
  70. progressBar.setVisibility(View.GONE);
  71. }
  72. @Override
  73. public void onLoadingComplete(String imageUri, View view,
  74. Bitmap loadedImage) {
  75. progressBar.setVisibility(View.GONE);
  76. mAttacher.update();
  77. }
  78. });
  79. }
  80. }

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

[java]  view plain copy print ?
  1. ImageView mImageView;
  2. PhotoViewAttacher mAttacher;
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. // Any implementation of ImageView can be used!
  8. mImageView = (ImageView) findViewById(R.id.iv_photo);
  9. // Set the Drawable displayed
  10. Drawable bitmap = getResources().getDrawable(R.drawable.wallpaper);
  11. mImageView.setImageDrawable(bitmap);
  12. // Attach a PhotoViewAttacher, which takes care of all of the zooming functionality.
  13. mAttacher = new PhotoViewAttacher(mImageView);
  14. }
  15. // If you later call mImageView.setImageDrawable/setImageBitmap/setImageResource/etc then you just need to call
  16. attacher.update();

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

[java]  view plain copy print ?
  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 plain copy print ?
  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了解的不深刻吧,希望以后加强学习,也希望以后跟你们交流学习,共同进步!

源码请在这里下载:http://download.csdn.net/detail/lee_tianya/8056359

微信朋友圈图片查看器的实现相关推荐

  1. iOS转场动画之微信朋友圈图片查看器

    前言 什么是转场动画呢?顾名思义,就是切换界面所用的动画效果.本文主要介绍的是modal的效果.当我们使用modal的时候,只需要使用 presentViewController:animated:c ...

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

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/40264551 看博文之前,希望大家先打开自己的微信点到朋友圈中去,仔细观察是不是发 ...

  3. 使用photoview+viewpager实现图片缩放切换(类似微信朋友圈图片查看)

    首先看一下最终效果 经过分析可知,整个页面布局应该是一个Listview,它的每一个条目item中包含原型头像(采用CircleImageVIew)一个数目可变的GridView和其他,Gridvie ...

  4. Android仿微信朋友圈图片展示效果,图片查看器

    现在越来越多的APP都会有图片展示,这里是模仿微信朋友圈图片展示效果,图片查看器. 主要分为4部分: 1.透明Activity 2.计算gridView下iamgeView Item所在位置 3.一张 ...

  5. canva画图 图片居中裁剪_css实现不定宽高的图片img居中裁剪_类似微信朋友圈图片效果...

    需求如下: 前端需要显示矩形的缩略图,接口返回的图片尺寸大小不一,宽高不相等,需要前端来处理并显示成正方形,类似微信朋友圈图片的效果,等比例正方形显示在列表中,让图片根据宽高来自适应显示在页面上.那么 ...

  6. Android仿微信朋友圈图片上传选择器布局

    标题有点绕口,直接上一个效果图,如果符合你的需求的请在往下看,避免浪费你的时间 当当当当,标红的区域就是今天我们要干的活了 ,搞起来! 思路: 对android有点了解的人都知道在列表显示中我们可以使 ...

  7. Android调用系统分享和指定app分享-微信朋友圈图文分享和qq分享

    Android调用系统分享和指定app分享-微信朋友圈图文分享和qq分享 标签: Android系统分享QQ分享朋友圈图文分享 2016-09-27 22:54 279人阅读 评论(0) 收藏 举报 ...

  8. 安卓开发仿微信图片拖拽_Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动)...

    [实例简介] Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动) [实例截图] [核心代码] ImageDemo-2014-02-18 └── ImageDemo-2014-02-18 ├ ...

  9. 类微信朋友圈图片放大效果,点击图片放大动画

    要用到的 就是坐标转换方法 - (CGRect)convertRect:(CGRect)rect toView:(UIView *)view; 1:我这里演示的是 tableviewHeader上子v ...

最新文章

  1. 前端组件库 - 搭建web app常用的样式/组件等收集列表(移动优先)
  2. linux查看当前shell的方法
  3. python2和pytho3切换_python2和pytho3切换_Python2和Python3共存安装
  4. matlab直流电机双闭环控制系统设计,基于MATLAB的直流电机双闭环调速系统设计毕业论文.doc...
  5. mysql 取左_MySQL select语句从字符串左侧获取5个字符
  6. 超级全面的权限系统设计方案
  7. 拒绝无用的长篇大论!仅12张图片,最全的中台精华都在这里了
  8. Linux 信号详解五(信号阻塞,信号未决)
  9. xp系统怎么添加ntp服务器,1 Windows xp NTP服务器的配置
  10. Win7远程桌面 提示 登录没有成功解决方法
  11. XYOJ1234出租车费
  12. Android 开发的现状及发展前景
  13. 传统蓝牙HCI连接的流程介绍
  14. 微软官方dllcache恢复的批处理
  15. 绝地求生显示器测试软件,《绝地求生大逃杀》1728*1080分辨率怎么设置?自定义分辨率设置方法分享...
  16. 游戏开发物语安卓!Android彻底组件化方案实践方法!快来收藏!
  17. 用GCTA计算亲缘关系矩阵和遗传力
  18. 使用深度学习Web项目的手写Marathi印地语字母书写和检测
  19. 华为认证--云计算HCIA-2
  20. 电脑密码解锁教程详细版图文教程

热门文章

  1. 【Matlab】最小二乘法拟合多项式
  2. 关于定时任务fixedRate和fixedDelay区别最简单的解释
  3. ORACLE数据库之ORA-02290检查校验问题解析
  4. 企业信用等级评价认证是什么
  5. 对JSON数据进行排序
  6. Linux模拟按键输入
  7. 微信小程序拍照和摄像功能实现方法示例
  8. MYSQL Function函数创建和调用
  9. 帮我综述一下人体步态协同分析的研究现状
  10. 4种整流电路、5种滤波电路