自定义带倒影和偏转的超炫Gallery

昨天晚上写的博客没有了,只好今天重新写一遍,重新学习下吧,首先,看下效果图:

先看下主类代码:

public class GalleryDemoActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.main);Integer[] images = { R.drawable.image01,R.drawable.image02,R.drawable.image03,R.drawable.image04,R.drawable.image05};ImageAdapter adapter = new ImageAdapter(this, images);adapter.createReflectedImages();//创建倒影效果GalleryFlow galleryFlow = (GalleryFlow) this.findViewById(R.id.gallery);galleryFlow.setFadingEdgeLength(0);galleryFlow.setSpacing(10); //图片之间的间距galleryFlow.setAdapter(adapter);galleryFlow.setOnItemClickListener(new OnItemClickListener() {public void onItemClick(AdapterView<?> parent, View view,int position, long id) {Toast.makeText(getApplicationContext(), String.valueOf(position), Toast.LENGTH_SHORT).show();}});galleryFlow.setSelection(4);} 比较简单,先来看下倒影效果是如何实现的,在ImageAdapter类里找到createReflectedImages()这个方法:/*** 创建倒影效果* @return*/public boolean createReflectedImages() {//倒影图和原图之间的距离final int reflectionGap = 4;int index = 0;for (int imageId : mImageIds) {//返回原图解码之后的bitmap对象Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), imageId);int width = originalImage.getWidth();int height = originalImage.getHeight();//创建矩阵对象Matrix matrix = new Matrix();//指定一个角度以0,0为坐标进行旋转// matrix.setRotate(30);//指定矩阵(x轴不变,y轴相反)matrix.preScale(1, -1);//将矩阵应用到该原图之中,返回一个宽度不变,高度为原图1/2的倒影位图Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,height/2, width, height/2, matrix, false);//创建一个宽度不变,高度为原图+倒影图高度的位图Bitmap bitmapWithReflection = Bitmap.createBitmap(width,(height + height / 2), Config.ARGB_8888);//将上面创建的位图初始化到画布Canvas canvas = new Canvas(bitmapWithReflection);canvas.drawBitmap(originalImage, 0, 0, null);Paint deafaultPaint = new Paint();deafaultPaint.setAntiAlias(false);// canvas.drawRect(0, height, width, height + reflectionGap,deafaultPaint);canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);Paint paint = new Paint();paint.setAntiAlias(false);/*** 参数一:为渐变起初点坐标x位置,* 参数二:为y轴位置,* 参数三和四:分辨对应渐变终点,* 最后参数为平铺方式,* 这里设置为镜像Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变*/LinearGradient shader = new LinearGradient(0,originalImage.getHeight(), 0,bitmapWithReflection.getHeight() + reflectionGap,0x70ffffff, 0x00ffffff, TileMode.MIRROR);//设置阴影paint.setShader(shader);paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));//用已经定义好的画笔构建一个矩形阴影渐变效果canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()+ reflectionGap, paint);//创建一个ImageView用来显示已经画好的bitmapWithReflectionImageView imageView = new ImageView(mContext);imageView.setImageBitmap(bitmapWithReflection);//设置imageView大小 ,也就是最终显示的图片大小imageView.setLayoutParams(new GalleryFlow.LayoutParams(200, 300));//imageView.setScaleType(ScaleType.MATRIX);mImages[index++] = imageView;}return true;}先获取倒影,然后把倒影和原照片合成一张图片。里面使用到了bitmap的静态方法createBitmap(),看下官方文档:public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)Since: API Level 1Returns an immutable bitmap from subset of the source bitmap, transformed by the optional matrix. It is initialized with the same density as the original bitmap.ParameterssourceThe bitmap we are subsettingxThe x coordinate of the first pixel in sourceyThe y coordinate of the first pixel in sourcewidthThe number of pixels in each rowheightThe number of rowsmOptional matrix to be applied to the pixelsfiltertrue if the source should be filtered. Only applies if the matrix contains more than just translation.ReturnsA bitmap that represents the specified subset of sourceThrowsIllegalArgumentExceptionif the x, y, width, height values are outside of the dimensions of the source bitmap. 参数x、y就是开始复制的起点坐标,就是从原图的那个坐标点开始复制,width设置复制的宽度,height设置高度。

因为代码中注释较详细,这里不再多说。

下面这段代码是设置渐变效果:

/*** 参数一:为渐变起初点坐标x位置,* 参数二:为y轴位置,* 参数三和四:分辨对应渐变终点,* 最后参数为平铺方式,* 这里设置为镜像Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变*/LinearGradient shader = new LinearGradient(0,originalImage.getHeight(), 0,bitmapWithReflection.getHeight() + reflectionGap,0x70ffffff, 0x00ffffff, TileMode.MIRROR); 看完倒影,再来看一下偏转,在main.xml文件中:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=""android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"><nsouth.jonas.android.GalleryFlowandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:id="@+id/gallery" /></LinearLayout>只有一个自定义的GalleryFlow,来看下它的代码:public class GalleryFlow extends Gallery{private Camera mCamera = new Camera();//相机类private int mMaxRotationAngle = 60;//最大转动角度private int mMaxZoom = -280;////最大缩放值private int mCoveflowCenter;//半径值public GalleryFlow(Context context) {super(context);//支持转换 ,执行getChildStaticTransformation方法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);}/*** 获取旋转最大角度* @return*/public int getMaxRotationAngle() {return mMaxRotationAngle;}/*** 设置旋转最大角度* @param maxRotationAngle*/public void setMaxRotationAngle(int maxRotationAngle) {mMaxRotationAngle = maxRotationAngle;}/*** 获取最大缩放值* @return*/public int getMaxZoom() {return mMaxZoom;}/*** 设置最大缩放值* @param maxZoom*/public void setMaxZoom(int maxZoom) {mMaxZoom = maxZoom;}/*** 获取半径值* @return*/private int getCenterOfCoverflow() {return (getWidth() – getPaddingLeft() – getPaddingRight()) / 2+ getPaddingLeft();}/*** @param view* @return*/private static int getCenterOfView(View view) {return view.getLeft() + view.getWidth() / 2;}//控制gallery中每个图片的旋转(重写的gallery中方法)protected boolean getChildStaticTransformation(View child, Transformation t) {//取得当前子view的半径值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 {//根据图片在gallery中的位置来计算图片的旋转角度rotationAngle = (int) (((float) (mCoveflowCenter – childCenter) / childWidth) * mMaxRotationAngle);System.out.println("rotationAngle:" +rotationAngle);//如果旋转角度绝对值大于最大旋转角度返回(-mMaxRotationAngle或mMaxRotationAngle;)if (Math.abs(rotationAngle) > mMaxRotationAngle) {rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;}transformImageBitmap((ImageView) child, t, rotationAngle);}return true;}/****/protected void onSizeChanged(int w, int h, int oldw, int oldh) {mCoveflowCenter = getCenterOfCoverflow();super.onSizeChanged(w, h, oldw, oldh);}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 inif (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();}}主要的方法就是://控制gallery中每个图片的旋转(重写的gallery中方法)protected boolean getChildStaticTransformation(View child, Transformation t) {//取得当前子view的半径值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 {//根据图片在gallery中的位置来计算图片的旋转角度rotationAngle = (int) (((float) (mCoveflowCenter – childCenter) / childWidth) * mMaxRotationAngle);System.out.println("rotationAngle:" +rotationAngle);//如果旋转角度绝对值大于最大旋转角度返回(-mMaxRotationAngle或mMaxRotationAngle;)if (Math.abs(rotationAngle) > mMaxRotationAngle) {rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;}transformImageBitmap((ImageView) child, t, rotationAngle);}return true;}先根据图片所处的位置计算出需要旋转的角度,然后进行旋转: //根据图片在gallery中的位置来计算图片的旋转角度rotationAngle = (int) (((float) (mCoveflowCenter – childCenter) / childWidth) * mMaxRotationAngle);System.out.println("rotationAngle:" +rotationAngle);//如果旋转角度绝对值大于最大旋转角度返回(-mMaxRotationAngle或mMaxRotationAngle;)if (Math.abs(rotationAngle) > mMaxRotationAngle) {rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;}transformImageBitmap((ImageView) child, t, rotationAngle);主要功能实现是在transformImageBitmap()这个方法: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 inif (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();}主要进行翻转操作。

肯承认错误则错已改了一半

自定义带倒影和偏转的超炫Gallery

相关文章:

你感兴趣的文章:

标签云: