Android照片墙加强版,使用ViewPager实现画廊效果

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


记得关于照片墙的文章我已经写过好几篇了,有最基本的照片墙,有瀑布流模式的照片墙,后来又在瀑布流的基础之上加入了查看大图和多点触控缩放的功能。总体来说,照片墙这个Demo在这几篇文章的改进中已经变得较为完善了,本想关于这个功能的系列到此为止,但有朋友跟我反应,觉得在查看大图的时候最好能通过左右滑动来浏览前后的图片。恩,确实,好像比较高端的一些应用都有这样的效果,那么本篇文章中我们来继续对照片墙这个Demo进行改进,让它变得更加高端大气上档次!


整理了一下思路,感觉自己去实现一套通过左右滑动来切换图片的功能非常不划算,需要编写不少的代码。这里为了要让实现简单化,我们准备使用Android提供的ViewPager来完成这个功能。


ViewPager的基本用法我就不在本文中介绍了,如果还不了解的朋友可以到王鹏兄那里先学习一下 http://blog.csdn.net/wangjinyu501/article/details/8169924 。


另外,本篇文章的代码是完全在之前文章的基础上进行开发的,所以如果你还没有看过我前面所写的关于照片墙的文章,建议先去阅读一下 Android瀑布流照片墙实现,体验不规则排列的美感 和 Android多点触控技术实战,自由地对图片进行缩放和移动 这两篇文章。


下面就让我们开始动手吧,打开PhotoWallFallsDemo这个项目,首先修改image_details.xml这个布局文件中的代码,如下所示:

  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.   
  6.     <android.support.v4.view.ViewPager  
  7.         android:id=“@+id/view_pager”  
  8.         android:layout_width=“match_parent”  
  9.         android:layout_height=“match_parent” >  
  10.     </android.support.v4.view.ViewPager>  
  11.   
  12.     <TextView  
  13.         android:id=“@+id/page_text”  
  14.         android:layout_width=“wrap_content”  
  15.         android:layout_height=“wrap_content”  
  16.         android:layout_alignParentBottom=“true”  
  17.         android:layout_centerHorizontal=“true”  
  18.         android:layout_marginBottom=“10dp”  
  19.         android:textColor=“#fff”  
  20.         android:textSize=“18sp” />  
  21.   
  22. </RelativeLayout>  
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </android.support.v4.view.ViewPager>

    <TextView
        android:id="@+id/page_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dp"
        android:textColor="#fff"
        android:textSize="18sp" />

</RelativeLayout>
这里我们在布局文件中放置了两个控件,ViewPager和TextView,其中ViewPager自然是用来管理所有的图片的了,而TextView则是用于显示当前图片的页数以及总页数。


然后新建一个zoom_image_layout.xml,在这里放入ZoomImageView控件,如下所示:

  1. <?xml version=“1.0” encoding=“utf-8”?>  
  2. <com.example.photowallfallsdemo.ZoomImageView xmlns:android=“http://schemas.android.com/apk/res/android”  
  3.     android:id=“@+id/zoom_image_view”  
  4.     android:layout_width=“match_parent”  
  5.     android:layout_height=“match_parent”  
  6.     android:background=“#000000” >  
  7.   
  8. </com.example.photowallfallsdemo.ZoomImageView>  
<?xml version="1.0" encoding="utf-8"?>
<com.example.photowallfallsdemo.ZoomImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/zoom_image_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000" >

</com.example.photowallfallsdemo.ZoomImageView>

接下来修改ImageDetailsActivity中的代码,在这里去实现ViewPager的具体功能,代码如下所示:

  1. public class ImageDetailsActivity extends Activity implements OnPageChangeListener {  
  2.   
  3.     /** 
  4.      * 用于管理图片的滑动 
  5.      */  
  6.     private ViewPager viewPager;  
  7.   
  8.     /** 
  9.      * 显示当前图片的页数 
  10.      */  
  11.     private TextView pageText;  
  12.   
  13.     @Override  
  14.     protected void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  17.         setContentView(R.layout.image_details);  
  18.         int imagePosition = getIntent().getIntExtra(“image_position”0);  
  19.         pageText = (TextView) findViewById(R.id.page_text);  
  20.         viewPager = (ViewPager) findViewById(R.id.view_pager);  
  21.         ViewPagerAdapter adapter = new ViewPagerAdapter();  
  22.         viewPager.setAdapter(adapter);  
  23.         viewPager.setCurrentItem(imagePosition);  
  24.         viewPager.setOnPageChangeListener(this);  
  25.         // 设定当前的页数和总页数  
  26.         pageText.setText((imagePosition + 1) + “/” + Images.imageUrls.length);  
  27.     }  
  28.   
  29.     /** 
  30.      * ViewPager的适配器 
  31.      *  
  32.      * @author guolin 
  33.      */  
  34.     class ViewPagerAdapter extends PagerAdapter {  
  35.   
  36.         @Override  
  37.         public Object instantiateItem(ViewGroup container, int position) {  
  38.             String imagePath = getImagePath(Images.imageUrls[position]);  
  39.             Bitmap bitmap = BitmapFactory.decodeFile(imagePath);  
  40.             if (bitmap == null) {  
  41.                 bitmap = BitmapFactory.decodeResource(getResources(),  
  42.                         R.drawable.empty_photo);  
  43.             }  
  44.             View view = LayoutInflater.from(ImageDetailsActivity.this).inflate(  
  45.                     R.layout.zoom_image_layout, null);  
  46.             ZoomImageView zoomImageView = (ZoomImageView) view  
  47.                     .findViewById(R.id.zoom_image_view);  
  48.             zoomImageView.setImageBitmap(bitmap);  
  49.             container.addView(view);  
  50.             return view;  
  51.         }  
  52.   
  53.         @Override  
  54.         public int getCount() {  
  55.             return Images.imageUrls.length;  
  56.         }  
  57.   
  58.         @Override  
  59.         public boolean isViewFromObject(View arg0, Object arg1) {  
  60.             return arg0 == arg1;  
  61.         }  
  62.   
  63.         @Override  
  64.         public void destroyItem(ViewGroup container, int position, Object object) {  
  65.             View view = (View) object;  
  66.             container.removeView(view);  
  67.         }  
  68.   
  69.     }  
  70.   
  71.     /** 
  72.      * 获取图片的本地存储路径。 
  73.      *  
  74.      * @param imageUrl 
  75.      *            图片的URL地址。 
  76.      * @return 图片的本地存储路径。 
  77.      */  
  78.     private String getImagePath(String imageUrl) {  
  79.         int lastSlashIndex = imageUrl.lastIndexOf(“/”);  
  80.         String imageName = imageUrl.substring(lastSlashIndex + 1);  
  81.         String imageDir = Environment.getExternalStorageDirectory().getPath()  
  82.                 + ”/PhotoWallFalls/”;  
  83.         File file = new File(imageDir);  
  84.         if (!file.exists()) {  
  85.             file.mkdirs();  
  86.         }  
  87.         String imagePath = imageDir + imageName;  
  88.         return imagePath;  
  89.     }  
  90.   
  91.     @Override  
  92.     public void onPageScrollStateChanged(int arg0) {  
  93.   
  94.     }  
  95.   
  96.     @Override  
  97.     public void onPageScrolled(int arg0, float arg1, int arg2) {  
  98.   
  99.     }  
  100.   
  101.     @Override  
  102.     public void onPageSelected(int currentPage) {  
  103.         // 每当页数发生改变时重新设定一遍当前的页数和总页数  
  104.         pageText.setText((currentPage + 1) + “/” + Images.imageUrls.length);  
  105.     }  
  106.   
  107. }  
public class ImageDetailsActivity extends Activity implements OnPageChangeListener {

    /**
     * 用于管理图片的滑动
     */
    private ViewPager viewPager;

    /**
     * 显示当前图片的页数
     */
    private TextView pageText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.image_details);
        int imagePosition = getIntent().getIntExtra("image_position", 0);
        pageText = (TextView) findViewById(R.id.page_text);
        viewPager = (ViewPager) findViewById(R.id.view_pager);
        ViewPagerAdapter adapter = new ViewPagerAdapter();
        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(imagePosition);
        viewPager.setOnPageChangeListener(this);
        // 设定当前的页数和总页数
        pageText.setText((imagePosition + 1) + "/" + Images.imageUrls.length);
    }

    /**
     * ViewPager的适配器
     * 
     * @author guolin
     */
    class ViewPagerAdapter extends PagerAdapter {

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            String imagePath = getImagePath(Images.imageUrls[position]);
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            if (bitmap == null) {
                bitmap = BitmapFactory.decodeResource(getResources(),
                        R.drawable.empty_photo);
            }
            View view = LayoutInflater.from(ImageDetailsActivity.this).inflate(
                    R.layout.zoom_image_layout, null);
            ZoomImageView zoomImageView = (ZoomImageView) view
                    .findViewById(R.id.zoom_image_view);
            zoomImageView.setImageBitmap(bitmap);
            container.addView(view);
            return view;
        }

        @Override
        public int getCount() {
            return Images.imageUrls.length;
        }

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

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

    }

    /**
     * 获取图片的本地存储路径。
     * 
     * @param imageUrl
     *            图片的URL地址。
     * @return 图片的本地存储路径。
     */
    private String getImagePath(String imageUrl) {
        int lastSlashIndex = imageUrl.lastIndexOf("/");
        String imageName = imageUrl.substring(lastSlashIndex + 1);
        String imageDir = Environment.getExternalStorageDirectory().getPath()
                + "/PhotoWallFalls/";
        File file = new File(imageDir);
        if (!file.exists()) {
            file.mkdirs();
        }
        String imagePath = imageDir + imageName;
        return imagePath;
    }

    @Override
    public void onPageScrollStateChanged(int arg0) {

    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {

    }

    @Override
    public void onPageSelected(int currentPage) {
        // 每当页数发生改变时重新设定一遍当前的页数和总页数
        pageText.setText((currentPage + 1) + "/" + Images.imageUrls.length);
    }

}
这个类也是实现滑动切换图片功能最主要的一个类了,由于ViewPager的用法并不复杂,所以这个类的代码也不多,下面我们来仔细地分析一下。


首先在onCreate()方法中要去加载我们刚刚修改的image_details.xml布局,然后要从Intent中取出当前要展示的那张图片的位置。接下来通过findViewById()方法获取到ViewPager和TextView控件的实例,并创建了一个ViewPagerAdapter对象作为ViewPager的适配器,之后去调用setCurrentItem()方法来设置当前显示的是哪一张图片。


那么这个ViewPagerAdapter又是什么呢?可以看到,它是一个继承了PagerAdapter的适配器,是专门用于在ViewPager中使用的。一般情况下我们都需要至少去重写PagerAdapter中的instantiateItem()、getCount()、isViewFromObject()和destroyItem()这四个方法。在instantiateItem()方法中,我们根据图片的位置获取到了图片对应的存储路径,然后调用BitmapFactory的解析方法将这张图片解析成一个Bitmap对象,接着实例化zoom_image_layout.xml这个布局,并获取其中的ZoomImageView控件,然后把Bitmap对象设定进去。在getCount()方法,只是简单地返回了一共有多少张图片。isViewFromObject()方法比较简单,就是判断两个参数是否相等就好。而destroyItem()方法中,则是要把应该销毁的View对象回收掉,以防止图片过多导致OOM出现。


另外,这里的ViewPager还注册了OnPageChangeListener接口,每当ViewPager的页数发现改变时,onPageSelected()方法就会调用。我们在这里让TextView显示当前图片的页数以及总页数即可。


目前的ImageDetailsActivity已经具备了翻页浏览图片的功能了,如果你心急的话,可以现在就运行试一试。不过一但你运行之后,就会发现,我们还有一些细节工作还没完成。比如说在onCreate()方法中会从Intent中取出要显示的那张图片的位置,而很明显目前是取不到了。于是,我们还需要修改MyScrollView中的代码,在这里将点击的那张图片的位置传递过来。由于这个类中的代码非常多,我只列出需要修改的那些部分,如下所示:

  1. public class MyScrollView extends ScrollView implements OnTouchListener {  
  2.   
  3.     ……  
  4.   
  5.     /** 
  6.      * 开始加载下一页的图片,每张图片都会开启一个异步线程去下载。 
  7.      */  
  8.     public void loadMoreImages() {  
  9.         if (hasSDCard()) {  
  10.             int startIndex = page * PAGE_SIZE;  
  11.             int endIndex = page * PAGE_SIZE + PAGE_SIZE;  
  12.             if (startIndex < Images.imageUrls.length) {  
  13.                 Toast.makeText(getContext(), ”正在加载…”, Toast.LENGTH_SHORT).show();  
  14.                 if (endIndex > Images.imageUrls.length) {  
  15.                     endIndex = Images.imageUrls.length;  
  16.                 }  
  17.                 for (int i = startIndex; i < endIndex; i++) {  
  18.                     LoadImageTask task = new LoadImageTask();  
  19.                     taskCollection.add(task);  
  20.                     task.execute(i);  
  21.                 }  
  22.                 page++;  
  23.             } else {  
  24.                 Toast.makeText(getContext(), ”已没有更多图片”, Toast.LENGTH_SHORT).show();  
  25.             }  
  26.         } else {  
  27.             Toast.makeText(getContext(), ”未发现SD卡”, Toast.LENGTH_SHORT).show();  
  28.         }  
  29.     }  
  30.   
  31.     /** 
  32.      * 遍历imageViewList中的每张图片,对图片的可见性进行检查,如果图片已经离开屏幕可见范围,则将图片替换成一张空图。 
  33.      */  
  34.     public void checkVisibility() {  
  35.         for (int i = 0; i < imageViewList.size(); i++) {  
  36.             ImageView imageView = imageViewList.get(i);  
  37.             int borderTop = (Integer) imageView.getTag(R.string.border_top);  
  38.             int borderBottom = (Integer) imageView.getTag(R.string.border_bottom);  
  39.             if (borderBottom > getScrollY() && borderTop < getScrollY() + scrollViewHeight) {  
  40.                 String imageUrl = (String) imageView.getTag(R.string.image_url);  
  41.                 Bitmap bitmap = imageLoader.getBitmapFromMemoryCache(imageUrl);  
  42.                 if (bitmap != null) {  
  43.                     imageView.setImageBitmap(bitmap);  
  44.                 } else {  
  45.                     LoadImageTask task = new LoadImageTask(imageView);  
  46.                     task.execute(i);  
  47.                 }  
  48.             } else {  
  49.                 imageView.setImageResource(R.drawable.empty_photo);  
  50.             }  
  51.         }  
  52.     }  
  53.   
  54.     ……  
  55.   
  56.     /** 
  57.      * 异步下载图片的任务。 
  58.      *  
  59.      * @author guolin 
  60.      */  
  61.     class LoadImageTask extends AsyncTask<Integer, Void, Bitmap> {  
  62.   
  63.         /** 
  64.          * 记录每个图片对应的位置 
  65.          */  
  66.         private int mItemPosition;  
  67.   
  68.         ……  
  69.   
  70.         @Override  
  71.         protected Bitmap doInBackground(Integer… params) {  
  72.             mItemPosition = params[0];  
  73.             mImageUrl = Images.imageUrls[mItemPosition];  
  74.             Bitmap imageBitmap = imageLoader.getBitmapFromMemoryCache(mImageUrl);  
  75.             if (imageBitmap == null) {  
  76.                 imageBitmap = loadImage(mImageUrl);  
  77.             }  
  78.             return imageBitmap;  
  79.         }  
  80.   
  81.         ……  
  82.   
  83.         /** 
  84.          * 向ImageView中添加一张图片 
  85.          *  
  86.          * @param bitmap 
  87.          *            待添加的图片 
  88.          * @param imageWidth 
  89.          *            图片的宽度 
  90.          * @param imageHeight 
  91.          *            图片的高度 
  92.          */  
  93.         private void addImage(Bitmap bitmap, int imageWidth, int imageHeight) {  
  94.             LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imageWidth,  
  95.                     imageHeight);  
  96.             if (mImageView != null) {  
  97.                 mImageView.setImageBitmap(bitmap);  
  98.             } else {  
  99.                 ImageView imageView = new ImageView(getContext());  
  100.                 imageView.setLayoutParams(params);  
  101.                 imageView.setImageBitmap(bitmap);  
  102.                 imageView.setScaleType(ScaleType.FIT_XY);  
  103.                 imageView.setPadding(5555);  
  104.                 imageView.setTag(R.string.image_url, mImageUrl);  
  105.                 imageView.setOnClickListener(new OnClickListener() {  
  106.                     @Override  
  107.                     public void onClick(View v) {  
  108.                         Intent intent = new Intent(getContext(), ImageDetailsActivity.class);  
  109.                         intent.putExtra(”image_position”, mItemPosition);  
  110.                         getContext().startActivity(intent);  
  111.                     }  
  112.                 });  
  113.                 findColumnToAdd(imageView, imageHeight).addView(imageView);  
  114.                 imageViewList.add(imageView);  
  115.             }  
  116.         }  
  117.           
  118.         ……  
  119.           
  120.     }  
  121.   
  122. }  
public class MyScrollView extends ScrollView implements OnTouchListener {

    ......

    /**
     * 开始加载下一页的图片,每张图片都会开启一个异步线程去下载。
     */
    public void loadMoreImages() {
        if (hasSDCard()) {
            int startIndex = page * PAGE_SIZE;
            int endIndex = page * PAGE_SIZE + PAGE_SIZE;
            if (startIndex < Images.imageUrls.length) {
                Toast.makeText(getContext(), "正在加载...", Toast.LENGTH_SHORT).show();
                if (endIndex > Images.imageUrls.length) {
                    endIndex = Images.imageUrls.length;
                }
                for (int i = startIndex; i < endIndex; i++) {
                    LoadImageTask task = new LoadImageTask();
                    taskCollection.add(task);
                    task.execute(i);
                }
                page++;
            } else {
                Toast.makeText(getContext(), "已没有更多图片", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(getContext(), "未发现SD卡", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 遍历imageViewList中的每张图片,对图片的可见性进行检查,如果图片已经离开屏幕可见范围,则将图片替换成一张空图。
     */
    public void checkVisibility() {
        for (int i = 0; i < imageViewList.size(); i++) {
            ImageView imageView = imageViewList.get(i);
            int borderTop = (Integer) imageView.getTag(R.string.border_top);
            int borderBottom = (Integer) imageView.getTag(R.string.border_bottom);
            if (borderBottom > getScrollY() && borderTop < getScrollY() + scrollViewHeight) {
                String imageUrl = (String) imageView.getTag(R.string.image_url);
                Bitmap bitmap = imageLoader.getBitmapFromMemoryCache(imageUrl);
                if (bitmap != null) {
                    imageView.setImageBitmap(bitmap);
                } else {
                    LoadImageTask task = new LoadImageTask(imageView);
                    task.execute(i);
                }
            } else {
                imageView.setImageResource(R.drawable.empty_photo);
            }
        }
    }

    ......

    /**
     * 异步下载图片的任务。
     * 
     * @author guolin
     */
    class LoadImageTask extends AsyncTask<Integer, Void, Bitmap> {

        /**
         * 记录每个图片对应的位置
         */
        private int mItemPosition;

        ......

        @Override
        protected Bitmap doInBackground(Integer... params) {
            mItemPosition = params[0];
            mImageUrl = Images.imageUrls[mItemPosition];
            Bitmap imageBitmap = imageLoader.getBitmapFromMemoryCache(mImageUrl);
            if (imageBitmap == null) {
                imageBitmap = loadImage(mImageUrl);
            }
            return imageBitmap;
        }

        ......

        /**
         * 向ImageView中添加一张图片
         * 
         * @param bitmap
         *            待添加的图片
         * @param imageWidth
         *            图片的宽度
         * @param imageHeight
         *            图片的高度
         */
        private void addImage(Bitmap bitmap, int imageWidth, int imageHeight) {
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imageWidth,
                    imageHeight);
            if (mImageView != null) {
                mImageView.setImageBitmap(bitmap);
            } else {
                ImageView imageView = new ImageView(getContext());
                imageView.setLayoutParams(params);
                imageView.setImageBitmap(bitmap);
                imageView.setScaleType(ScaleType.FIT_XY);
                imageView.setPadding(5, 5, 5, 5);
                imageView.setTag(R.string.image_url, mImageUrl);
                imageView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent intent = new Intent(getContext(), ImageDetailsActivity.class);
                        intent.putExtra("image_position", mItemPosition);
                        getContext().startActivity(intent);
                    }
                });
                findColumnToAdd(imageView, imageHeight).addView(imageView);
                imageViewList.add(imageView);
            }
        }

        ......

    }

}

可以看到,这里我们将LoadImageTask 的泛型进行了修改,doInBackground不再接收一个字符串数组,而是接收一个整型数组,这里传入的参数也就代表着每张图片的位置。这样的话,每个调用LoadImageTask 的地方也都需要进行相应的修改,在loadMoreImages()和checkVisibility()方法中,都将传入的参数改成了图片的位置。最后在addImage()方法中,使用Intent将点击的那张图片对应的位置传递给了ImageDetailsActivity。


目前看上去一切都完美了吧!但其实还有一点工作我们还没完成。由于ViewPager的事件和ZoomImageView的事件是存在冲突的,所以加入了ViewPager后,ZoomImageView本身的单个手指拖动图片的功能会受很大的影响。所以我们还需要在ZoomImageView的onTouchEvent()中进行判断,如果当前的图片是没有缩放的,则允许通过滑动来切换图片,如果当前的图片已经放大了,则要屏蔽掉ViewPager的事件,这样ZoomImageView本身的事件就不会受影响。代码如下所示:

  1. public class ZoomImageView extends View {  
  2.   
  3.     ……  
  4.   
  5.     @Override  
  6.     public boolean onTouchEvent(MotionEvent event) {  
  7.         if (initRatio == totalRatio) {  
  8.             getParent().requestDisallowInterceptTouchEvent(false);  
  9.         } else {  
  10.             getParent().requestDisallowInterceptTouchEvent(true);  
  11.         }  
  12.         ……  
  13.         return true;  
  14.     }  
  15.   
  16.     ……  
  17.   
  18. }  
public class ZoomImageView extends View {

    ......

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (initRatio == totalRatio) {
            getParent().requestDisallowInterceptTouchEvent(false);
        } else {
            getParent().requestDisallowInterceptTouchEvent(true);
        }
        ......
        return true;
    }

    ......

}

这里使用getParent()获取到的就是ViewPager对象,然后调用requestDisallowInterceptTouchEvent()方法来启动和禁用ViewPager的功能。


好了,这样的话,所有的代码就已经完成了,可以运行一下看看完整的效果了。点击任意一张图片可以查看大图,然后通过左右滑动可以浏览前后的图片,并且仍然能够通过多点触控对图片进行缩放,效果如下图所示:




除了滑动切换图片之外,在屏幕的底部还能显示当前图片的页数以及总页数,功能已经是相当完善了。目前这个照片墙Demo的效果已经不亚于市场上一些常见的图片浏览程序了吧。


好了,今天的讲解到此结束,有疑问的朋友请在下面留言。


源码下载,请点击这里


blockquote{ border-left: 10px solid rgba(128,128,128,0.075); background-color: rgba(128,128,128,0.05); border-radius: 0 5px 5px 0; padding: 15px 20px;

关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

微信扫一扫下方二维码即可关注:

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值