android自定义view拉扯图片,android开发篇:不压缩加载大图片的自定义view实现上...

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

ActionBar的开发是App开发中比较重要的一环,虽然自定义actionbar既灵活又简单,但是不符合规范,适配性便不是最强的,所以了解好ActionBar依然是相当重要。

自定义view的基本实现

初始化和覆写onDraw方法就完成了自定义view,能够实现加载一张图片。

public MapView(Context context) {

super(context);

this.context=context;

init();

}

public MapView(Context context,AttributeSet a) {

super(context,a);

this.context=context;

init();

}

private void init(){

bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.map);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if(bitmap!=null)

canvas.drawBitmap(bitmap, matrix, null);

}

图片滑动

但这还远远不够,起码要实现基本的图片滑动吧,所以要覆写onTouchEvent方法。

@Override

public boolean onTouchEvent(MotionEvent event) {

switch( event.getAction()){

case MotionEvent.ACTION_DOWN:

fingerOriginP.x = event.getX();

fingerOriginP.y = event.getY();

break;

case MotionEvent.ACTION_MOVE:

if(fingerOriginDistanceF==-1){

float currentX=event.getX();

float currentY=event.getY();

matrix.postTranslate(currentX- fingerOriginP.x, currentY-fingerOriginP.y);

fingerOriginP.x = currentX;

fingerOriginP.y = currentY;

}

invalidate();

break;

}

return true;

};

图片放大和缩小

图片只能移动不能缩小也是不允许的,所以贪心的我继续探究将放大和缩小写进onTouchEvent中。

@Override

public boolean onTouchEvent(MotionEvent event) {

switch( event.getAction()){

case MotionEvent.ACTION_DOWN:

fingerOriginP.x = event.getX();

fingerOriginP.y = event.getY();

break;

case MotionEvent.ACTION_MOVE:

if(event.getPointerCount()>=2){

if(fingerOriginDistanceF!=-1){

float currentDistanceF=(float) Math.sqrt((Math.pow(event.getX(0)-event.getX(1), 2)+Math.pow(event.getY(0)-event.getY(1), 2)));

scaleRate*=currentDistanceF/fingerOriginDistanceF;

matrix.postScale(currentDistanceF/fingerOriginDistanceF, currentDistanceF/fingerOriginDistanceF,screenP.x/2,screenP.y/2);

fingerOriginDistanceF=currentDistanceF;

}

else{

fingerOriginDistanceF=(float) Math.sqrt((Math.pow(event.getX(0)-event.getX(1), 2)+Math.pow(event.getY(0)-event.getY(1), 2)));

}

}

else if(fingerOriginDistanceF==-1){

float currentX=event.getX();

float currentY=event.getY();

matrix.postTranslate(currentX- fingerOriginP.x, currentY-fingerOriginP.y);

fingerOriginP.x = currentX;

fingerOriginP.y = currentY;

}

invalidate();

break;

case MotionEvent.ACTION_UP:

if(fingerOriginDistanceF!=-1){

fingerOriginDistanceF=-1;

}

initBitmap();

}

return true;

};

大图片的加载

重点到了,虽然大图片我们通常可以进行压缩处理,这是最简单直接的做法,但是我就是要像地图一样显示超大图片,且保证清晰度怎么做,则只能裁剪了。图片的加载由于比较耗时间我放到了线程里,滑动的代码也要相应改动。

private Handler handler=new Handler(new Handler.Callback() {

@Override

public boolean handleMessage(Message msg) {

bitmap=(Bitmap) msg.obj;

float[] values=getMatrixValues();

values[2]=0;

values[5]=0;

matrix.setValues(values);

invalidate();

return false;

}

});

private void init(){

fingerOriginP=new PointF();

screenP=new PointF();

fingerDefaultP=new PointF();

DisplayMetrics dm=context.getResources().getDisplayMetrics();

screenP.x=dm.widthPixels;

screenP.y=dm.heightPixels;

matrix=new Matrix();

initBitmap();

}

@SuppressLint("NewApi") private void initBitmap(){

new Thread(new Runnable() {

@Override

public void run() {

Bitmap bitmap=null;

try {

InputStream inputStream = context.getAssets().open("map.jpg");

BitmapFactory.Options options = new BitmapFactory.Options();

// BitmapFactory.decodeStream(inputStream,null,options);

BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, false);

options.inPreferredConfig = Bitmap.Config.RGB_565;

bitmap=bitmapRegionDecoder.decodeRegion(new Rect((int) (fingerDefaultP.x),(int) ( fingerDefaultP.y), (int) ( fingerDefaultP.x+screenP.x/scaleRate),(int) ( fingerDefaultP.y+screenP.y/scaleRate)), options);

} catch (IOException e) {

Log.d("test","Error");

e.printStackTrace();

}

Message msg=new Message();

msg.obj=bitmap;

handler.sendMessage(msg);

}

}).start();

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch( event.getAction()){

case MotionEvent.ACTION_DOWN:

fingerOriginP.x = event.getX();

fingerOriginP.y = event.getY();

break;

case MotionEvent.ACTION_MOVE:

if(event.getPointerCount()>=2){

if(fingerOriginDistanceF!=-1){

float currentDistanceF=(float) Math.sqrt((Math.pow(event.getX(0)-event.getX(1), 2)+Math.pow(event.getY(0)-event.getY(1), 2)));

scaleRate*=currentDistanceF/fingerOriginDistanceF;

matrix.postScale(currentDistanceF/fingerOriginDistanceF, currentDistanceF/fingerOriginDistanceF,screenP.x/2,screenP.y/2);

scaleM.postScale(currentDistanceF/fingerOriginDistanceF, currentDistanceF/fingerOriginDistanceF,screenP.x/2,screenP.y/2);

fingerOriginDistanceF=currentDistanceF;

}

else{

fingerOriginDistanceF=(float) Math.sqrt((Math.pow(event.getX(0)-event.getX(1), 2)+Math.pow(event.getY(0)-event.getY(1), 2)));

}

}

else if(fingerOriginDistanceF==-1){

float currentX=event.getX();

float currentY=event.getY();

fingerTranslateP.x-=(currentX- fingerOriginP.x)/scaleRate;

fingerTranslateP.y-=(currentY- fingerOriginP.y)/scaleRate;

matrix.postTranslate(currentX- fingerOriginP.x, currentY-fingerOriginP.y);

fingerOriginP.x = currentX;

fingerOriginP.y = currentY;

}

invalidate();

break;

case MotionEvent.ACTION_UP:

if(fingerOriginDistanceF!=-1){

fingerOriginDistanceF=-1;

float []scaleValues=getMatrixValues(scaleM);

fingerScaleP.x=-scaleValues[2]/scaleRate;

fingerScaleP.y=-scaleValues[5]/scaleRate;

}

fingerDefaultP.x=(fingerScaleP.x+fingerTranslateP.x);

fingerDefaultP.y=(fingerScaleP.y+fingerTranslateP.y);

initBitmap();

}

return true;

};

如你所见,这里用了两个Matrix,因为一个matrix每次更新视图前都要把values[2]和values[5],即平移位置为0,使得每次视图都显示剪切部分的左上角。另一个scaleM是用来记录放大信息的,因为前一个Matrix每次将values[2]和values[5]置为0后第二次放大会受影响,并不能得到实际的放大偏移量。另外,有两个记录偏移量的分别是fingerScaleP和fingerTranslateP对应记录因为放大产生的偏移量和因为滑动产生的偏移量,最后加起来便是总的偏移量。

感谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值