最近研究了一下如何在Android上实现CoverFlow效果的控件,其实早在2010年,就有Neil Davies开发并开源出了这个控件,Neil大神的这篇博客地址http://www.inter-fuser.com/2010/02/android-coverflow-widget-v2.html。首先是阅读源码,弄明白核心思路后,自己重新写了一遍这个控件,并加入了详尽的注释以便日后查阅;而后在使用过程中,发现了有两点可以改进:(1)初始图片位于中间,左边空了一半空间,比较难看,可以改为重复滚动地展示、(2)由于图片一开始就需要加载出来,所以对内存开销较大,很容易OOM,需要对图片的内存空间进行压缩。
这个自定义控件包括4个部分,用于创建及提供图片对象的ImageAdapter,计算图片旋转角度等的自定义控件GalleryFlow,压缩采样率解析Bitmap的工具类BitmapScaleDownUtil,以及承载自定义控件的Gallery3DActivity。
首先是ImageAdapter,代码如下:
package pym.test.gallery3d.widget; import pym.test.gallery3d.util.BitmapScaleDownUtil; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Shader.TileMode; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; /** * @author pengyiming * @date 2013-9-30 * @function GalleryFlow适配器 */ public class ImageAdapter extends BaseAdapter { /* 数据段begin */ private final String TAG = "ImageAdapter"; private Context mContext; //图片数组 private int[] mImageIds ; //图片控件数组 private ImageView[] mImages; //图片控件LayoutParams private GalleryFlow.LayoutParams mImagesLayoutParams; /* 数据段end */ /* 函数段begin */ public ImageAdapter(Context context, int[] imageIds) { mContext = context; mImageIds = imageIds; mImages = new ImageView[mImageIds.length]; mImagesLayoutParams = new GalleryFlow.LayoutParams(Gallery.LayoutParams.WRAP_CONTENT, Gallery.LayoutParams.WRAP_CONTENT); } /** * @function 根据指定宽高创建待绘制的Bitmap,并绘制到ImageView控件上 * @param imageWidth * @param imageHeight * @return void */ public void createImages(int imageWidth, int imageHeight) { // 原图与倒影的间距5px final int gapHeight = 5; int index = 0; for (int imageId : mImageIds) { /* step1 采样方式解析原图并生成倒影 */ // 解析原图,生成原图Bitmap对象 // Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), imageId); Bitmap originalImage = BitmapScaleDownUtil.decodeSampledBitmapFromResource(mContext.getResources(), imageId, imageWidth, imageHeight); int width = originalImage.getWidth(); int height = originalImage.getHeight(); // Y轴方向反向,实质就是X轴翻转 Matrix matrix = new Matrix(); matrix.setScale(1, -1); // 且仅取原图下半部分创建倒影Bitmap对象 Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false); /* step2 绘制 */ // 创建一个可包含原图+间距+倒影的新图Bitmap对象 Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + gapHeight + height / 2), Config.ARGB_8888); // 在新图Bitmap对象之上创建画布 Canvas canvas = new Canvas(bitmapWithReflection); // 抗锯齿效果 canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG)); // 绘制原图 canvas.drawBitmap(originalImage, 0, 0, null); // 绘制间距 Paint gapPaint = new Paint(); gapPaint.setColor(0xFFCCCCCC); canvas.drawRect(0, height, width, height + gapHeight, gapPaint); // 绘制倒影 canvas.drawBitmap(reflectionImage, 0, height + gapHeight, null); /* step3 渲染 */ // 创建一个线性渐变的渲染器用于渲染倒影 Paint paint = new Paint(); LinearGradient shader = new LinearGradient(0, height, 0, (height + gapHeight + height / 2), 0x70ffffff, 0x00ffffff, TileMode.CLAMP); // 设置画笔渲染器 paint.setShader(shader); // 设置图片混合模式 paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // 渲染倒影+间距 canvas.drawRect(0, height, width, (height + gapHeight + height / 2), paint); /* step4 在ImageView控件上绘制 */ ImageView imageView = new ImageView(mContext); imageView.setImageBitmap(bitmapWithReflection); imageView.setLayoutParams(mImagesLayoutParams); // 打log imageView.setTag(index); /* step5 释放heap */ originalImage.recycle(); reflectionImage.recycle(); // bitmapWithReflection.recycle(); mImages[index++] = imageView; } } @Override public int getCount() { return Integer.MAX_VALUE; } @Override public Object getItem(int position) { return mImages[position]; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { return mImages[position % mImages.length]; } /* 函数段end */ }
查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/extra/
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, android canvas
, 控件
, imageview
, bitmap
, graphics
, import
, coverflow gallery
, imageview控件
, 图片压缩canvas
, imageview图片android
, imageview代码控件gridview
, 图片控件android
height
android coverflow、android cover flow、android实现coverflow、androidd coverflow、coverflow,以便于您获取更多的相关知识。