Android:自定义ImageView

时间:2012-02-25 13:14:58

标签: android

我正在尝试通过创建自定义ImageView为图像添加触摸功能,但是当我运行它时,我在logcat中获得了Null点异常。我的代码如下:

TouchImageView.java

package com.android.wayfinder;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;

public class TouchImageView extends ImageView { 

Matrix matrix = new Matrix(); 

// We can be in one of these 3 states 
static final int NONE = 0; 
static final int DRAG = 1; 
static final int ZOOM = 2; 
int mode = NONE; 

// Remember some things for zooming 
PointF last = new PointF(); 
PointF start = new PointF(); 
float minScale = 1f; 
float maxScale = 3f; 
float[] m; 

float redundantXSpace, redundantYSpace; 

float width, height; 
static final int CLICK = 3; 
float saveScale = 1f; 
float right, bottom, origWidth, origHeight, bmWidth, bmHeight; 

ScaleGestureDetector mScaleDetector; 

Context context; 

public TouchImageView(Context context) { 
    super(context); 
    super.setClickable(true); 
    this.context = context; 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    matrix.setTranslate(1f, 1f); 
    m = new float[9]; 
    setImageMatrix(matrix); 
    setScaleType(ScaleType.MATRIX); 

    setOnTouchListener(new OnTouchListener() { 

        public boolean onTouch(View v, MotionEvent event) { 
            mScaleDetector.onTouchEvent(event); 

            matrix.getValues(m); 
            float x = m[Matrix.MTRANS_X]; 
            float y = m[Matrix.MTRANS_Y]; 
            PointF curr = new PointF(event.getX(), event.getY()); 

            switch (event.getAction()) { 
                case MotionEvent.ACTION_DOWN: 
                    last.set(event.getX(), event.getY()); 
                    start.set(last); 
                    mode = DRAG; 
                    break; 
                case MotionEvent.ACTION_MOVE: 
                    if (mode == DRAG) { 
                        float deltaX = curr.x - last.x; 
                        float deltaY = curr.y - last.y; 
                        float scaleWidth = Math.round(origWidth * saveScale); 
                        float scaleHeight = Math.round(origHeight * saveScale); 
                        if (scaleWidth < width) { 
                            deltaX = 0; 
                            if (y + deltaY > 0) 
                                deltaY = -y; 
                            else if (y + deltaY < -bottom) 
                                deltaY = -(y + bottom);  
                        } else if (scaleHeight < height) { 
                            deltaY = 0; 
                            if (x + deltaX > 0) 
                                deltaX = -x; 
                            else if (x + deltaX < -right) 
                                deltaX = -(x + right); 
                        } else { 
                            if (x + deltaX > 0) 
                                deltaX = -x; 
                            else if (x + deltaX < -right) 
                                deltaX = -(x + right); 

                            if (y + deltaY > 0) 
                                deltaY = -y; 
                            else if (y + deltaY < -bottom) 
                                deltaY = -(y + bottom); 
                        } 
                        matrix.postTranslate(deltaX, deltaY); 
                        last.set(curr.x, curr.y); 
                    } 
                    break; 

                case MotionEvent.ACTION_UP: 
                    mode = NONE; 
                    int xDiff = (int) Math.abs(curr.x - start.x); 
                    int yDiff = (int) Math.abs(curr.y - start.y); 
                    if (xDiff < CLICK && yDiff < CLICK) 
                        performClick(); 
                    break; 

                case MotionEvent.ACTION_POINTER_UP: 
                    mode = NONE; 
                    break; 
            } 
            setImageMatrix(matrix); 
            invalidate(); 
            return true; // indicate event was handled 
        } 

    }); 
} 

@Override 
public void setImageBitmap(Bitmap bm) {  
    super.setImageBitmap(bm); 
    bmWidth = bm.getWidth(); 
    bmHeight = bm.getHeight(); 
} 

public void setMaxZoom(float x) 
{ 
    maxScale = x; 
} 

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
    @Override 
    public boolean onScaleBegin(ScaleGestureDetector detector) { 
        mode = ZOOM; 
        return true; 
    } 

    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
        float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05); 
        float origScale = saveScale; 
        saveScale *= mScaleFactor; 
        if (saveScale > maxScale) { 
            saveScale = maxScale; 
            mScaleFactor = maxScale / origScale; 
        } else if (saveScale < minScale) { 
            saveScale = minScale; 
            mScaleFactor = minScale / origScale; 
        } 
        right = width * saveScale - width - (2 * redundantXSpace * saveScale); 
        bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 
        if (origWidth * saveScale <= width || origHeight * saveScale <= height) { 
            matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2); 
            if (mScaleFactor < 1) { 
                matrix.getValues(m); 
                float x = m[Matrix.MTRANS_X]; 
                float y = m[Matrix.MTRANS_Y]; 
                if (mScaleFactor < 1) { 
                    if (Math.round(origWidth * saveScale) < width) { 
                        if (y < -bottom) 
                            matrix.postTranslate(0, -(y + bottom)); 
                        else if (y > 0) 
                            matrix.postTranslate(0, -y); 
                    } else { 
                        if (x < -right)  
                            matrix.postTranslate(-(x + right), 0); 
                        else if (x > 0)  
                            matrix.postTranslate(-x, 0); 
                    } 
                } 
            } 
        } else { 
            matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); 
            matrix.getValues(m); 
            float x = m[Matrix.MTRANS_X]; 
            float y = m[Matrix.MTRANS_Y]; 
            if (mScaleFactor < 1) { 
                if (x < -right)  
                    matrix.postTranslate(-(x + right), 0); 
                else if (x > 0)  
                    matrix.postTranslate(-x, 0); 
                if (y < -bottom) 
                    matrix.postTranslate(0, -(y + bottom)); 
                else if (y > 0) 
                    matrix.postTranslate(0, -y); 
            } 
        } 
        return true; 

    } 
} 

@Override 
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) 
{ 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    width = MeasureSpec.getSize(widthMeasureSpec); 
    height = MeasureSpec.getSize(heightMeasureSpec); 
    //Fit to screen. 
    float scale; 
    float scaleX =  (float)width / (float)bmWidth; 
    float scaleY = (float)height / (float)bmHeight; 
    scale = Math.min(scaleX, scaleY); 
    matrix.setScale(scale, scale); 
    setImageMatrix(matrix); 
    saveScale = 1f; 

    // Center the image 
    redundantYSpace = (float)height - (scale * (float)bmHeight) ; 
    redundantXSpace = (float)width - (scale * (float)bmWidth); 
    redundantYSpace /= (float)2; 
    redundantXSpace /= (float)2; 

    matrix.postTranslate(redundantXSpace, redundantYSpace); 

    origWidth = width - 2 * redundantXSpace; 
    origHeight = height - 2 * redundantYSpace; 
    right = width * saveScale - width - (2 * redundantXSpace * saveScale); 
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 
    setImageMatrix(matrix); 
} 

}



ImageView.xml

<?xml version="1.0" encoding="utf-8"?>

<com.android.wayfinder.TouchImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/arasnalaoi"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/aras_na_laoi" />


Activity:

public class ImageActivity extends Activity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


            TouchImageView touch = (TouchImageView) this.findViewById(R.id.arasnalaoi);
            touch.setImageBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.aras_na_laoi));
            touch.setMaxZoom(4f);
            setContentView(touch);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    }

}


The null pointer exception is pointing at the line: touch.setImageBitmap... 

I'm absolutely stumpt so any help would be greatly appreciated. 

Shaw

2 个答案:

答案 0 :(得分:0)

您对this.findViewById的调用返回null(即touch为空)。它找不到R.id.arasn​​alaoi TouchImageView,因为您还没有将内容视图加载到您的活动中。

你想要以不同的顺序做事,即

  1. 使用setContentView(R.layout.imageView);加载您的内容,假设您的xml位于布局文件夹中。

  2. 使用TouchImageView touch = (TouchImageView) this.findViewById(R.id.arasnalaoi)查找您的观点;

  3. 设置touch对象的属性。

答案 1 :(得分:0)

您收到NullPointerException,因为在为活动设置内容视图之前致电findViewById,因此TouchImageView touch = (TouchImageView) this.findViewById(R.id.arasnalaoi)无法找到R.id.arasnalaoi作为ID的任何视图,它肯定会返回null,是的,touch为null,这就是抛出NullPointerException的原因。