[view] 11_3DGallery图库

Android 4.0

3DGallery图库

一、倒影、遮罩、渐变、抗锯齿、合成1、定义一个类 CustomeGallery继承Gallery
2、将资源图片转成Bitmap
3、进行翻转,合成,保存到一个List
4、通过ListView展示出来
5、代码:
ImageAdapter.java
package cn.zengfansheng.customeGallery.adapter;
 
import java.util.ArrayList;
import java.util.List;
 
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.PorterDuffXfermode;
import android.graphics.Shader;
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.Gallery.LayoutParams;
import android.widget.ImageView;
 
public class ImageAdapter extends BaseAdapter {
 
    private Context context;
    private int[] imageIds;
    private List<ImageView> imageViews;
 
    public ImageAdapter(Context context, int[] imageIds) {
        this.context = context;
        this.imageIds = imageIds;
        imageViews = new ArrayList<ImageView>();
 
    }
 
    /**
     * 生成倒影的图片,并合成
     */

    public void getInvertImage() {
 
        int interval = 5;//间隔,原始图片和倒影图片的间隔
 
        for (int i = 0; i < imageIds.length; i++) {
 
            //1、获取原始bitmap
            Bitmap resourceBitmap = BitmapFactory.decodeResource(context.getResources(), imageIds[i]);
 
            // 原始bitmap的宽高
            int width = resourceBitmap.getWidth();
            int height = resourceBitmap.getHeight();
 
            //2、获取倒影bitmap
            Matrix matrix = new Matrix();
            float[] values = new float[]{
                    1,0,0,
                    0,-1,resourceBitmap.getHeight(),
                    0,0,1
            };
            matrix.setValues(values);
            // matrix.setRotate(180, 1, -1);
            //倒影的bitmap
            Bitmap invertBitmap = Bitmap.createBitmap(resourceBitmap,0,height/2,width,height/2, matrix, false);
 
            //3、创建一个空的bitmap
            Config config = Config.ARGB_8888;// 4B表示一个像素
            Bitmap resultBitmap = Bitmap.createBitmap(width, (int) (height * 1.5 + 10), config);
 
            // 4、用画笔在这空白的bitmap上画
            Canvas canvas = new Canvas(resultBitmap);
 
            // 4-1画原始bitmap
            Paint defaultPaint = new Paint();
            canvas.drawBitmap(resourceBitmap, 0, 0, defaultPaint);
 
            // 画个矩形间隔
            canvas.drawRect(0, height, width, height + interval, defaultPaint);
 
            // 4-2画倒影的bimmap
            canvas.drawBitmap(invertBitmap, 0, height + interval, defaultPaint);
 
            // 5、设置给ImageView并抗锯齿
            BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), resultBitmap);
            bitmapDrawable.setAntiAlias(true);// 抗锯齿,平滑效果
 
            ImageView iv = new ImageView(context);
            iv.setImageDrawable(bitmapDrawable);
 
            // 7、设置显示图片的大小
            @SuppressWarnings("deprecation")
            LayoutParams params = new LayoutParams(160, 320);
            iv.setLayoutParams(params);
 
            // 8、遮罩
            Paint paint = new Paint();
            paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));
 
            // 9、渐变
            Shader shader = new LinearGradient(0, height, 0, resultBitmap.getHeight(),0x70ffffff, 0x00ffffff, TileMode.CLAMP);
            paint.setShader(shader );
            canvas.drawRect(0, height, width, resultBitmap.getHeight(), paint);
 
            // 10、加到集合中去
            imageViews.add(iv);
 
        }
    }
 
    @Override
    public int getCount() {
        if (imageViews != null) {
            return imageViews.size();// 擦,没有return
        }
        return 0;
    }
 
    @Override
    public Object getItem(int position) {
        return null;
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return imageViews.get(position);
    }
}
二、变形
CustomeGallery.java
package cn.zengfansheng.customeGallery.view;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Transformation;
import android.widget.Gallery;
import android.widget.ImageView;
/**
 * 自定义的Gallery
 * @author hacket
 */
@SuppressWarnings("deprecation")
public class CustomeGallery extends Gallery {
    
    private int currentCenterOfGallery;// 展示图片的中心点
    public CustomeGallery(Context context, AttributeSet attrs) {
        super(context, attrs);
        setStaticTransformationsEnabled(true);// 可以转化(变形)
    }
    public CustomeGallery(Context context,int[] imageIds) {
        super(context);
        setStaticTransformationsEnabled(true);// 可以转化(变形)
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        currentCenterOfGallery = getCurrentCenterOfGallery();
    }
    // 1、获取grallery展示图片的中心点
    public int getCurrentCenterOfGallery(){
        // (grallery宽度-左边paddingLeft-右边paddingRigth)/2+左边paddingLeft
        // getLeft()+getWidth()/2;
        return (getWidth()-getPaddingLeft()-getPaddingRight())/2+getPaddingLeft();
    }
    // 2、获取图片的中心点
    public int getCurrentCenterOfView(View view) {
        return view.getLeft() + view.getWidth() / 2;
    }
    // 3、
    @Override
    protected boolean getChildStaticTransformation(View child, Transformation t) {
        // 得到图片的中心点
        int currentOfChild = getCurrentCenterOfView(child);
        int childHeight = child.getLayoutParams().height;
        int childWidth = child.getLayoutParams().width;
        int rotateAngle = 0;// 旋转的角度
        t.clear();// 清理之前的转换
        // 图片变形的风格样式
        t.setTransformationType(Transformation.TYPE_MATRIX);
        if (currentOfChild == currentCenterOfGallery) {
            // 是中心位置,旋转角度为0
            transformationBitmap((ImageView) child, t, 0);
        } else {
            // 不是中心位置
            rotateAngle = (int) ((float)(currentCenterOfGallery - currentOfChild) /childWidth  * maxRotateAngle);
            if(Math.abs(rotateAngle) > maxRotateAngle){//旋转角度绝对值大于最大等于maxRotateAngle
                rotateAngle = rotateAngle < 0 ? -maxRotateAngle : maxRotateAngle;
            }
            transformationBitmap((ImageView) child, t, rotateAngle);
        }
        return true;
    }
    private Camera camera = new Camera();
    
    private int maxZoom = -250;//最大缩放值
    
    private int maxRotateAngle = 50;//最大旋转角度
    
    // 图片变形
    private void transformationBitmap(ImageView child,Transformation t,int rotateAngle){
        
        camera.save();//保存
        
        Matrix imageMatrix = 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(imageMatrix);
        // Preconcats matrix相当于右乘矩阵
        // Postconcats matrix相当于左乘矩阵。
        imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
        imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
        camera.restore();// 还原
    }
}

OOM问题:如果加载的图片过多,内存会溢出,程序崩溃
使用软引用
SoftReference()来包裹ImageView
System.gc() 通知垃圾回收器回收垃圾
问题1:每次都要暂停那么几十ms(看log)
问题2:只是显示说明要调用垃圾回收器来回收垃圾,但并不能保证立刻就运行垃圾回收器来回收垃圾
Indicates to the VM that it would be a good time to run the garbage collector. Note that this is a hint only. There is no guarantee that the garbage collector will actually be run.

解决OOM问题:如果加载的图片过多,会导致OOM溢出

解决:使用软引用SoftReference,
a) new出来一个map用来存储软引用对象
private Map<Integer, SoftReference<ImageView>> map =  new HashMap<Integer, SoftReference<ImageView>>();
b)将ImageView对象存储到软引用中去
public void intiImageView(){
    for (int i = 0; i < imageIds.length; i++) {
        // 通过id获取倒影合成的ImageView
        ImageView invertImageView = getInvertImage(imageIds[i]);
        // 用一个软引用关联该倒影ImageView
        SoftReference<ImageView> softReferenceIV = new SoftReference<ImageView>(invertImageView);
        // 将该软引用加到map中去
        map.put(i, softReferenceIV);
    }
}  
c) 从软引用中获取ImageView,get(),如果返回null,说明已经被垃圾回收器给回收了,
不为null的话,那么为该ImageView对象
// 从集合中获取指定位置的软引用
SoftReference<ImageView> ivSoftReference = map.get(position);
// 获取该软引用引用的对象
ImageView imageView = ivSoftReference.get();//得到所引用的对象,如果为null,表示已经被垃圾回收器回收
if (imageView == null) {// 如果为null,说明已经被回收,那么重新创建一个
    Log.i(TAG"回收对象:"+position);
    imageView = getInvertImage(imageIds[position]);
}
// 否则,用该软引用所引用的对象
return imageView; 
结果:
可以看到,当到了15后,14,13直接从软引用中get()数据了,而不是重新创建对象