博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Android自带Gallery组件实现CoverFlow
阅读量:6271 次
发布时间:2019-06-22

本文共 11194 字,大约阅读时间需要 37 分钟。

源代码转载自国外Neil Davies,使用Apache2.0开源协议

实现了一个自定义的ImageAdapter,为图片制作倒影效果。

传入参数为context和程序内drawable中的图片ID数组。之后调用其中的createReflectedImages()方法分别创造每一个图像的倒影效果,生成对应的ImageView数组,最后在getView()中返回。

/** Copyright (C) 2010 Neil Davies** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.* * This code is base on the Android Gallery widget and was Created * by Neil Davies neild001 'at' gmail dot com to be a Coverflow widget* * @author Neil Davies*/public class ImageAdapter extends BaseAdapter {int mGalleryItemBackground;private Context mContext;private Integer[] mImageIds ;private ImageView[] mImages;public ImageAdapter(Context c, int[] ImageIds) {mContext = c;mImageIds = ImageIds;mImages = new ImageView[mImageIds.length];}public boolean createReflectedImages() {// The gap we want between the reflection and the original imagefinal int reflectionGap = 4;int index = 0;for (int imageId : mImageIds) {Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), imageId);int width = originalImage.getWidth();int height = originalImage.getHeight();// This will not scale but will flip on the Y axisMatrix matrix = new Matrix();matrix.preScale(1, -1);// Create a Bitmap with the flip matrix applied to it.// We only want the bottom half of the imageBitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,height / 2, width, height / 2, matrix, false);// Create a new bitmap with same width but taller to fit reflectionBitmap bitmapWithReflection = Bitmap.createBitmap(width,(height + height / 2), Config.ARGB_8888);// Create a new Canvas with the bitmap that's big enough for the image plus gap plus reflectionCanvas canvas = new Canvas(bitmapWithReflection);// Draw in the original imagecanvas.drawBitmap(originalImage, 0, 0, null);// Draw in the gapPaint deafaultPaint = new Paint();canvas.drawRect(0, height, width, height + reflectionGap,deafaultPaint);// Draw in the reflectioncanvas.drawBitmap(reflectionImage, 0, height + reflectionGap,null);// Create a shader that is a linear gradient that covers the// reflectionPaint paint = new Paint();LinearGradient shader = new LinearGradient(0,originalImage.getHeight(), 0,bitmapWithReflection.getHeight() + reflectionGap,0x70ffffff, 0x00ffffff, TileMode.CLAMP);// Set the paint to use this shader (linear gradient)paint.setShader(shader);// Set the Transfer mode to be porter duff and destination inpaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));// Draw a rectangle using the paint with our linear gradientcanvas.drawRect(0, height, width,bitmapWithReflection.getHeight() + reflectionGap, paint);ImageView imageView = new ImageView(mContext);imageView.setImageBitmap(bitmapWithReflection);imageView.setLayoutParams(new GalleryFlow.LayoutParams(160, 240));// imageView.setScaleType(ScaleType.MATRIX);mImages[index++] = imageView;}return true;}public int getCount() {return mImageIds.length;}public Object getItem(int position) {return position;}public long getItemId(int position) {return position;}public View getView(int position, View convertView, ViewGroup parent) {// Use this code if you want to load from resources/** ImageView i = new ImageView(mContext);* i.setImageResource(mImageIds[position]); i.setLayoutParams(new* CoverFlow.LayoutParams(350,350));* i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);* * //Make sure we set anti-aliasing otherwise we get jaggies* BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();* drawable.setAntiAlias(true); return i;*/return mImages[position];}// Returns the size (0.0f to 1.0f) of the views depending on the 'offset' to the center.public float getScale(boolean focused, int offset) {/* Formula: 1 / (2 ^ offset) */return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));}}}

仅仅实现了图片的倒影效果还不够,因为在coverflow中图片切换是有旋转和缩放效果的,而自带的gallery中并没有实现。因此,扩展自带的 gallery,实现自己的galleryflow。在原gallery类中,提供了一个方法 getChildStaticTransformation()以实现对图片的变换。通过覆写这个方法并在其中调用自定义的 transformImageBitmap(“每个图片与gallery中心的距离”)方法,,即可实现每个图片做相应的旋转和缩放。其中使用了 camera和matrix用于视图变换。具体可参考代码注释。

public class GalleryFlow extends Gallery {        // Graphics Camera used for transforming the matrix of ImageViews        private Camera mCamera = new Camera();        //The maximum angle the Child ImageView will be rotated by        private int mMaxRotationAngle = 60;       // The maximum zoom on the centre Child         private int mMaxZoom = -120;         // The Centre of the Coverflow         */        private int mCoveflowCenter;        public GalleryFlow(Context context) {                super(context);                this.setStaticTransformationsEnabled(true);        }        public GalleryFlow(Context context, AttributeSet attrs) {                super(context, attrs);                this.setStaticTransformationsEnabled(true);        }        public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {                super(context, attrs, defStyle);                this.setStaticTransformationsEnabled(true);        }        /**         * Get the max rotational angle of the image * @return the mMaxRotationAngle         */        public int getMaxRotationAngle() {                return mMaxRotationAngle;        }        /**         * Set the max rotational angle of each image * @param maxRotationAngle the mMaxRotationAngle to set         */        public void setMaxRotationAngle(int maxRotationAngle) {                mMaxRotationAngle = maxRotationAngle;        }        /**         * Get the Max zoom of the centre image @return the mMaxZoom         */        public int getMaxZoom() {                return mMaxZoom;        }        /**         * Set the max zoom of the centre image @param maxZoom* the mMaxZoom to set         */        public void setMaxZoom(int maxZoom) {                mMaxZoom = maxZoom;        }        /**         * Get the Centre of the Coverflow         *          * @return The centre of this Coverflow.         */        private int getCenterOfCoverflow() {                return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2                                + getPaddingLeft();        }        /**         * Get the Centre of the View @return The centre of the given view.         */        private static int getCenterOfView(View view) {                return view.getLeft() + view.getWidth() / 2;        }        /**         * {
@inheritDoc} @see #setStaticTransformationsEnabled(boolean) */ protected boolean getChildStaticTransformation(View child, Transformation t) { final int childCenter = getCenterOfView(child); final int childWidth = child.getWidth(); int rotationAngle = 0; t.clear(); t.setTransformationType(Transformation.TYPE_MATRIX); if (childCenter == mCoveflowCenter) { transformImageBitmap((ImageView) child, t, 0); } else { rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle); if (Math.abs(rotationAngle) > mMaxRotationAngle) { rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle; } transformImageBitmap((ImageView) child, t, rotationAngle); } return true; } /** * This is called during layout when the size of this view has changed. If * you were just added to the view hierarchy, you're called with the old * values of 0. * @param w Current width of this view. * @param h Current height of this view. * @param oldw Old width of this view. * @param oldh Old height of this view. */ protected void onSizeChanged(int w, int h, int oldw, int oldh) { mCoveflowCenter = getCenterOfCoverflow(); super.onSizeChanged(w, h, oldw, oldh); } /** * Transform the Image Bitmap by the Angle passed * @param imageView ImageView the ImageView whose bitmap we want to rotate * @param t transformation * @param rotationAngle the Angle by which to rotate the Bitmap */ private void transformImageBitmap(ImageView child, Transformation t, int rotationAngle) { mCamera.save(); final Matrix imageMatrix = t.getMatrix(); final int imageHeight = child.getLayoutParams().height; final int imageWidth = child.getLayoutParams().width; final int rotation = Math.abs(rotationAngle); // 在Z轴上正向移动camera的视角,实际效果为放大图片。 // 如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。 mCamera.translate(0.0f, 0.0f, 100.0f); // As the angle of the view gets less, zoom in if (rotation < mMaxRotationAngle) { float zoomAmount = (float) (mMaxZoom + (rotation * 1.5)); mCamera.translate(0.0f, 0.0f, zoomAmount); } // 在Y轴上旋转,对应图片竖向向里翻转。 // 如果在X轴上旋转,则对应图片横向向里翻转。 mCamera.rotateY(rotationAngle); mCamera.getMatrix(imageMatrix); imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2)); imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2)); mCamera.restore(); }}

下面是调用的Activity示例:

public void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                                                setContentView(R.layout.layout_gallery);                                Integer[] images = { R.drawable.img0001, R.drawable.img0030,                        R.drawable.img0100, R.drawable.img0130, R.drawable.img0200,                        R.drawable.img0230, R.drawable.img0300, R.drawable.img0330,                        R.drawable.img0354 };                                ImageAdapter adapter = new ImageAdapter(this, images);                adapter.createReflectedImages();                GalleryFlow galleryFlow = (GalleryFlow) findViewById(R.id.gallery_flow);                galleryFlow.setAdapter(adapter);                        }

PS1:

可以看出来这样实现的gallery锯齿问题比较严重。可以在createReflectedImages()使用以下代码:

BitmapDrawable bd = new BitmapDrawable(bitmapWithReflection);bd.setAntiAlias(true);

然后用iv.setImageDrawable(bd);

代替iv.setImageBitmap(bitmapWithReflection);
即可基本消除锯齿。
PS2:
ImageAdapter有待确定的MemoryLeak问题,貌似的Bitmap的decode方法会造成ML,使用ImageAdapter时多次旋 转屏幕后会出现OOM。目前可以通过将使用完毕的bimap调用recycle()方法和设置null并及时调用system.gc()得到一些改善,但 是问题并不明显。

 

转载于:https://www.cnblogs.com/JoannaQ/archive/2013/03/07/2947890.html

你可能感兴趣的文章
检索 COM 类工厂中 CLSID 为{00024500-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005。...
查看>>
测试java的父子类化
查看>>
HDOJ 1008
查看>>
安装thrift出现的一些问题
查看>>
makefile编写---单个子目录编译模板
查看>>
Oracle DB_LINK如何使用
查看>>
cv resource
查看>>
关于加快INSERT语句执行速度和HINT /*+ append */及/*+ append nologging */的使用
查看>>
JDK源代码学习系列07----Stack
查看>>
firefox
查看>>
PS批处理的使用
查看>>
七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】
查看>>
Quartz作业调度框架
查看>>
腾讯云下安装 nodejs + 实现 Nginx 反向代理
查看>>
js-权威指南学习笔记13
查看>>
《超级时间整理术》晨读笔记
查看>>
Spring Boot 2.0(二):Spring Boot 2.0尝鲜-动态 Banner
查看>>
Delphi IdTCPClient IdTCPServer 点对点传送文件
查看>>
Delphi中使用ActiveX的一些心得
查看>>
QT5.8.0+MSVC2015安装以及环境配置(不需要安装VS2015)
查看>>