Android自定义View之Gallery实现3D图片播放器
2014-10-25 20:35
555 查看
转载请注明出处:/article/10736890.html
最近在学习自定义View。刚好有讲到Gallery控件,所以今天就弄出来和大家一起分享分享。
首先我们来看看效果吧:
ps:不知道为什么,上传的gif图都不会动的。这让我很困扰!
接下来就是贴代码了,先看看目录:
MainActivity.java主Activity文件内容比较简单,没什么好说的:
接下来就是MyAdapter.java了,该类继承BaseAdapter,并对图片资源进行了投影操作:
主要的方法createReflectedBitmap()在代码中有详细的说明了,在这就不赘述了。大致的步骤是:得到源图片-->根据源图片绘制阴影图片-->创建一个画布大小为源图片大小加上阴影图片大小-->将源图片和阴影加入到画布-->得到带有阴影的图片效果。
然后就是MyGallery.java,该类实现图片的旋转:
可能是判断中间点的数据有问题,所以才会出现中间图片不是正面显示的效果。
最后是布局文件activity_main.xml:
好了,也没什么好说的了。附上源码下载地址:
源码下载
最近在学习自定义View。刚好有讲到Gallery控件,所以今天就弄出来和大家一起分享分享。
首先我们来看看效果吧:
ps:不知道为什么,上传的gif图都不会动的。这让我很困扰!
接下来就是贴代码了,先看看目录:
MainActivity.java主Activity文件内容比较简单,没什么好说的:
package com.example.mygallerydemo; import com.example.mygallery.MyGallery; import com.example.mygalleryadapter.MyAdapter; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; /** * * @author Joker_Ya * */ public class MainActivity extends ActionBarActivity { private MyGallery myGallery; private MyAdapter adapter; private int[] imageIds = new int[] { R.drawable.girl1, R.drawable.girl2, R.drawable.girl3, R.drawable.girl4, R.drawable.girl5, R.drawable.girl6 }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myGallery = (MyGallery) findViewById(R.id.my_gallery); adapter = new MyAdapter(this, imageIds); adapter.createReflectedBitmap(); myGallery.setAdapter(adapter); } }
接下来就是MyAdapter.java了,该类继承BaseAdapter,并对图片资源进行了投影操作:
package com.example.mygalleryadapter; import com.example.mygallery.MyGallery; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; /** * * @author Joker_Ya * */ public class MyAdapter extends BaseAdapter { private Context context; private int[] imageIds; private ImageView[] images; public MyAdapter(Context context, int[] imageIds) { super(); this.context = context; this.imageIds = imageIds; images = new ImageView[imageIds.length]; } @Override public int getCount() { // TODO Auto-generated method stub return images.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View arg1, ViewGroup arg2) { // TODO Auto-generated method stub return images[position]; } /** * 生成带有阴影效果的图片 */ @SuppressWarnings("deprecation") public void createReflectedBitmap() { // TODO Auto-generated method stub int index = 0; int ReflectionGap = 4;// 原图片于倒影之间的距离 for (int imageId : imageIds) { // 源图片 Bitmap resourceBitmap = BitmapFactory.decodeResource( context.getResources(), imageId); // 得到源图片的宽高 int width = resourceBitmap.getWidth(); int height = resourceBitmap.getHeight(); Matrix matrix = new Matrix(); // x水平翻转 y垂直翻转 1 正常 -1翻转 matrix.setScale(1, -1); // 生成倒影图片(设置其宽为源图片的宽 高为源图片高的一半) // Bitmap.createBitmap(source, x, y, width, height, m, filter); // Bitmap source 源图片 // x,y 生成倒影图片的起始位置 左上角 // width,height 图片的宽高 // Matrix m 用来 设置图片的样式 (倒影) Bitmap reflectionBitmap = Bitmap.createBitmap(resourceBitmap, 0, height / 2, width, height / 2, matrix, false); // 生成带有倒影的图片 宽为源图片的宽(width) // 高为源图片的高(height)加上倒影图片的高度(height/2) Bitmap bitmap = Bitmap.createBitmap(width, height + height / 2, Config.ARGB_8888); // 以带有倒影图片的宽高生成一样大小的画布 Canvas canvas = new Canvas(bitmap); // 绘制源图片 canvas.drawBitmap(resourceBitmap, 0, 0, null); // 绘制矩形--原图片于倒影之间的距离 Paint defpaint = new Paint(); canvas.drawRect(0, height, width, height + ReflectionGap, defpaint); // 绘制倒影图片 canvas.drawBitmap(reflectionBitmap, 0, height + ReflectionGap, null); Paint paint = new Paint(); // 遮罩 paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // 渐变 // 0x70ffffff, 0x00ffffff 渐变颜色范围ARGB /* * //线性渐变填充 shader着色器 //在位图上Y方向花砖模式 TileMode:(一共有三种) * CLAMP :如果渲染器超出原始边界范围,会复制范围内边缘染色。 * REPEAT :横向和纵向的重复渲染器图片,平铺。 * MIRROR :横向和纵向的重复渲染器图片,这个和REPEAT 重复方式不一样,他是以镜像方式平铺。 */ LinearGradient gradient = new LinearGradient(0, height, 0, bitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.CLAMP); // 着色器 用来绘制颜色 上色的 paint.setShader(gradient); canvas.drawRect(0, height, width, bitmap.getHeight(), paint); // 加入图片 ImageView imageView = new ImageView(context); BitmapDrawable bd = new BitmapDrawable(bitmap); // 消除图片锯齿效果 平滑 bd.setAntiAlias(true); imageView.setImageDrawable(bd); // 设置图片的大小 imageView.setLayoutParams(new MyGallery.LayoutParams(320, 480)); // 将图片加入到ImageView[]数组中去 images[index++] = imageView; } } }
主要的方法createReflectedBitmap()在代码中有详细的说明了,在这就不赘述了。大致的步骤是:得到源图片-->根据源图片绘制阴影图片-->创建一个画布大小为源图片大小加上阴影图片大小-->将源图片和阴影加入到画布-->得到带有阴影的图片效果。
然后就是MyGallery.java,该类实现图片的旋转:
package com.example.mygallery; import android.content.Context; import android.graphics.Camera; import android.graphics.Matrix; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.animation.Transformation; import android.widget.Gallery; import android.widget.ImageView; /** * * @author Joker_Ya * */ @SuppressWarnings("deprecation") public class MyGallery extends Gallery { private Camera camera = new Camera();// 相机 用于对图片进行变化 private int maxRotateAngle = 50;// 最大旋转角度 private int maxZoom = -250;// 最大缩放值 private int currentOfGallery;// gallery中心点 public MyGallery(Context context) { super(context); // TODO Auto-generated constructor stub // 允许对图片进行修改 setStaticTransformationsEnabled(true); } public MyGallery(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub setStaticTransformationsEnabled(true); } // 获得gallery展示图片的中心点 public int getCurrentOfGallery() { // 返回会gallery的中心点:gallery的宽度减去左右边距的一半再加上左边距就为gallery的中心点 return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft(); } // 获得图片的中心店 public int getCurrentOfView(View view) { return view.getLeft() + view.getWidth() / 2; } // 横竖屏改变的时候调用 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // TODO Auto-generated method stub currentOfGallery = getCurrentOfGallery(); super.onSizeChanged(w, h, oldw, oldh); } @Override protected boolean getChildStaticTransformation(View child, Transformation t) { // TODO Auto-generated method stub // 得到图片的中心点和宽高 int currentOfChild = getCurrentOfView(child); int width = child.getWidth(); // int height=child.getLayoutParams().height; int rotateAngle = 0;// 旋转角度 t.clear(); // 图片变形的风格样式 t.setTransformationType(Transformation.TYPE_MATRIX); Log.v(child.getId() + "currentOfChild", currentOfChild + ""); Log.v(child.getId() + "currentOfGallery", currentOfGallery + ""); if (currentOfChild == currentOfGallery) {// 判断图片是否为gallery的中心位置 // 在中心位置 transformationBitmap((ImageView) child, t, 0); } else { // 不在中心位置 rotateAngle = (int) ((float) (currentOfGallery - currentOfChild) / width * maxRotateAngle);// 获得旋转角度 if (Math.abs(rotateAngle) > maxRotateAngle) { // 旋转角度>最大旋转角度 // 判断rotateAngle是否小于零 小于则返回-maxRotateAngle 否则返回maxRotateAngle rotateAngle = rotateAngle < 0 ? -maxRotateAngle : maxRotateAngle; } transformationBitmap((ImageView) child, t, rotateAngle); } return true; } /** * 图片变形 * * @param child * 需要变形的图片 * @param t * 变形的风格样式 * @param rotateAngle * 旋转角度 */ private void transformationBitmap(ImageView child, Transformation t, int rotateAngle) { // TODO Auto-generated method stub camera.save();// 保存 Matrix matrix = t.getMatrix(); int rotate = Math.abs(rotateAngle); int imageWidth = child.getWidth(); int imageHeight = child.getHeight(); // z轴 正数 图片变大 x水平移动 y垂直移动 camera.translate(0.0f, 0.0f, 100.0f); if (rotate < maxRotateAngle) { float zoom = (float) (rotate * 1.5 + maxZoom); camera.translate(0.0f, 0.0f, zoom); child.setAlpha((int) (255 - rotate * 2.5)); } // 图片向展示中心 进行垂直角度的旋转 camera.rotateY(rotateAngle); camera.getMatrix(matrix); // Preconcats matrix相当于右乘矩阵 // Postconcats matrix相当于左乘矩阵。 /* * 这两行代码意思可能就不那么明显了,先说如果不加这两行代码,会是一个什么情况, 默认情况下,动画是以对象的左上角为起点的,如果这样的话, * 动画的效果就变成了可见对象在它的左上角开始,逐渐向右下角扩大,这显然不是我们期望的。 * 所以我们前面用到的halfWidth,halfHeight就用到了,这里保存了可见对象的一半宽度和高度,也就是中点, * 使用上面这两个方法后,就会改变动画的起始位置,动画默认是从右下角开始扩大的, * 使用matrix.preTranslate(-halfWidth, -halfHeight) 就把扩散点移到了中间, * 同样,动画的起始点为左上角,使用matrix.postTranslate(halfWidth, * halfHeight)就把起始点移到了中间, 这样就实现我们期望的效果了。 */ matrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2)); matrix.postTranslate((imageWidth / 2), (imageHeight / 2)); camera.restore();// 还原 } }
可能是判断中间点的数据有问题,所以才会出现中间图片不是正面显示的效果。
最后是布局文件activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000000" tools:context="com.example.mygallerydemo.MainActivity" > <com.example.mygallery.MyGallery android:id="@+id/my_gallery" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </RelativeLayout>
好了,也没什么好说的了。附上源码下载地址:
源码下载
相关文章推荐
- Android自定义Gallery控件实现3D图片浏览器
- 【Android界面实现】自定义Gallery控件实现简单3D图片浏览器
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- Android自定义View之三角,五角星,圆形,心形图片实现
- Android 自定义View消除锯齿实现图片旋转,添加边框及文字说明
- android 自定义imageview实现 图片放大缩小
- Android-自定义TextView和异步加载图片的实现
- Android 自定义RecyclerView 实现真正的Gallery效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果 .
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- Android实现自定义view---绘制图片
- android自定义Gallery实现手动和自动循环滚动切换图片
- Android 自定义RecyclerView 实现真正的Gallery效果
- android 自定义ImageView实现图片手势滑动、多点触摸缩放
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- android 自定义View用三张图片实现七个音量等级的录音效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- Android-自定义TextView和异步加载图片的实现
- Android开发之自定义圆角矩形图片ImageView的实现