快三个月了没写博客了,因为工作调动,很多经验、心得都没有时间记录下来。现在时间稍微充裕了点,我会尽量抽时间将之前想写而没写的东西补上。进入正题。
    去年某个时候,我偶然看到一篇文章,讲android里面放大镜的实现。文章很乱,没有格式,基本上属于看不下去的那种。虽然体裁很有意思,但是我也没有足够的内力把它看完。不过看到一句关键的话,说是使用带圆形的Drawable。这句话就够了,他下面写的一堆东西我也懒得看,于是就自己开始尝试,然后就做出来了。现在代码贴出来分享。
Java代码  
package chroya.demo.magnifier;  

import android.content.Context;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.graphics.BitmapShader;  
import android.graphics.Canvas;  
import android.graphics.Matrix;  
import android.graphics.Shader.TileMode;  
import android.graphics.drawable.ShapeDrawable;  
import android.graphics.drawable.shapes.OvalShape;  
import android.view.MotionEvent;  
import android.view.View;  

/** 
 * 放大镜实现方式1 
 * @author chroya 
 * 
*/  
public class ShaderView extends View{  
private Bitmap bitmap;  
private ShapeDrawable drawable;  
//放大镜的半径  
    private static final int RADIUS = 80;  
//放大倍数  
    private static final int FACTOR = 3;  
private Matrix matrix = new Matrix();  

public ShaderView(Context context) {  
super(context);  
        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.show);  
        bitmap = bmp;         
        BitmapShader shader = new BitmapShader(  
                Bitmap.createScaledBitmap(bmp, bmp.getWidth()*FACTOR,  
                        bmp.getHeight()*FACTOR, true), TileMode.CLAMP, TileMode.CLAMP);  
//圆形的drawable  
        drawable = new ShapeDrawable(new OvalShape());  
        drawable.getPaint().setShader(shader);  
        drawable.setBounds(0, 0, RADIUS*2, RADIUS*2);  
    }     

    @Override  
public boolean onTouchEvent(MotionEvent event) {  
final int x = (int) event.getX();  
final int y = (int) event.getY();  
//这个位置表示的是,画shader的起始位置  
        matrix.setTranslate(RADIUS-x*FACTOR, RADIUS-y*FACTOR);  
        drawable.getPaint().getShader().setLocalMatrix(matrix);  
//bounds,就是那个圆的外切矩形  
        drawable.setBounds(x-RADIUS, y-RADIUS, x+RADIUS, y+RADIUS);  
        invalidate();  
return true;  
    }  

    @Override  
public void onDraw(Canvas canvas) {  
super.onDraw(canvas);  
        canvas.drawBitmap(bitmap, 0, 0, null);  
        drawable.draw(canvas);  
    }  
}  

    基本原理就是使用ShapeDrawable构造一个圆形的drawable,然后它的paint的shader设置为将要放大的图片,然后就是简单的位置移动问题了。放大镜的半径和放大倍数都可以在代码里面修改,代码都有注释,应该很好理解了。

    不过,一个问题如果只有一种解决方法的话,那未免有点令人沮丧,想玩点另类的都不行。
    玩程序就得玩出个性,玩出激情。哈哈,废话太多,切回正题。

    再来看看放大镜的另外一种实现吧 ^-^
Java代码  
package chroya.demo.magnifier;  

import android.content.Context;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.graphics.Canvas;  
import android.graphics.Matrix;  
import android.graphics.Path;  
import android.graphics.Path.Direction;  
import android.view.MotionEvent;  
import android.view.View;  

/** 
 * 放大镜实现方式2 
 * @author chroya 
 * 
*/  
public class PathView extends View{  
private Path mPath = new Path();  
private Matrix matrix = new Matrix();  
private Bitmap bitmap;  
//放大镜的半径  
    private static final int RADIUS = 80;  
//放大倍数  
    private static final int FACTOR = 2;  
private int mCurrentX, mCurrentY;  

public PathView(Context context) {  
super(context);  
        mPath.addCircle(RADIUS, RADIUS, RADIUS, Direction.CW);  
        matrix.setScale(FACTOR, FACTOR);  

        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.show);  
    }     

    @Override  
public boolean onTouchEvent(MotionEvent event) {  
        mCurrentX = (int) event.getX();  
        mCurrentY = (int) event.getY();  

        invalidate();  
return true;  
    }  

    @Override  
public void onDraw(Canvas canvas) {  
super.onDraw(canvas);  
//底图  
        canvas.drawBitmap(bitmap, 0, 0, null);  
//剪切  
        canvas.translate(mCurrentX - RADIUS, mCurrentY - RADIUS);  
        canvas.clipPath(mPath);   
//画放大后的图  
        canvas.translate(RADIUS-mCurrentX*FACTOR, RADIUS-mCurrentY*FACTOR);  
        canvas.drawBitmap(bitmap, matrix, null);          
    }  
}  

    这里使用的是Path类,将canvas剪切出一块圆形区域,在其上绘制放大的部分。
    两种方式的效果都一样,如图:

    放大两倍的效果。


     放大三倍

     貌似还缺点什么,是吧? 嘿嘿,就是放大镜外面缺个框。那玩意,我没资源,所以懒得弄了,有兴趣的自己加吧。

    工程见附件。

编辑器加载中...