Android 获取imageView空引用错误-为什么?

Android 获取imageView空引用错误-为什么?,android,android-layout,android-canvas,Android,Android Layout,Android Canvas,我正在图像视图上绘制一个可重新调整大小的矩形 用于绘制自定义可重新调整大小的矩形视图的视图类: public class DrawPolygonCanvas extends View implements OnTouchListener { private final String TAG = "DrawLineCanvas"; private final String defaultROI = "Roi1:0.2,0.2|0.8,0.2|0.8,0.8|0.2,0.8";

我正在图像视图上绘制一个可重新调整大小的矩形

用于绘制自定义可重新调整大小的矩形视图的视图类:

public class DrawPolygonCanvas extends View implements OnTouchListener {

    private final String TAG = "DrawLineCanvas";
    private final String defaultROI = "Roi1:0.2,0.2|0.8,0.2|0.8,0.8|0.2,0.8";
    private Context context;
    private CanvasTouchManager canvasTouchManager = new CanvasTouchManager();
    private boolean isInitialized = false;
    private Paint circlePaint, linePaint;
    private String cameraROI = "";

    // Debug helpers to draw lines between the two touch points
    private HashMap<String, List<Vector2D>> polygons = new HashMap();

    public DrawPolygonCanvas(Context context) {
        super(context);
        init(context);
    }

    public DrawPolygonCanvas(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public DrawPolygonCanvas(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public DrawPolygonCanvas(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context context) {
        Log.e(TAG, "called init");
        this.context = context;
        Log.e(TAG, "calling setOnTouchListener");
        setOnTouchListener(this);
    }

    public void clearROI() {
        Log.e(TAG, "called clearROI");
        // Get ROI from the shared preferences.
        SharedPreferences prefs = UserSharedPref.initializeSharedPreferencesForCameraROI(context);
        cameraROI = prefs.getString(UserSharedPref.cameraROI, cameraROI);
        Log.e(TAG, "Reloaded ROI = " + cameraROI);
        convertString2Polygons();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.e(TAG, "called onDraw");
        super.onDraw(canvas);

        if (!isInitialized) {
            // Get ROI from the shared preferences.
            SharedPreferences prefs = UserSharedPref.initializeSharedPreferencesForCameraROI(context);
            cameraROI = prefs.getString(UserSharedPref.cameraROI, cameraROI);
            if (cameraROI.isEmpty()) {
                cameraROI = defaultROI;
            }
            convertString2Polygons();

            circlePaint = new Paint();
            circlePaint.setColor(0xFFFF0000);

            linePaint = new Paint();
            linePaint.setColor(0xFF00FF00);
            linePaint.setStyle(Paint.Style.STROKE);
            linePaint.setStrokeWidth(10);

            isInitialized = true;
        }

        Rect dest = new Rect(0, 0, getWidth(), getHeight());
        Paint paint = new Paint();
        paint.setFilterBitmap(true);


        exampleActivity ex = new exampleActivity();
        Bitmap bm = ex.getBitmap();

        canvas.drawBitmap(bm, null, dest, paint);

        try {
            for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {

                List<Vector2D> polygon = entry.getValue();

                for (int i = 0; i < polygon.size() - 1; i++) {
                    canvas.drawLine(polygon.get(i).getX(), polygon.get(i).getY(), polygon.get(i + 1).getX(), polygon.get(i + 1).getY(), linePaint);
                }
                canvas.drawLine(polygon.get(polygon.size() - 1).getX(), polygon.get(polygon.size() - 1).getY(), polygon.get(0).getX(), polygon.get(0).getY(), linePaint);

                for (int i = 0; i < polygon.size(); i++) {
                    canvas.drawCircle(polygon.get(i).getX(), polygon.get(i).getY(), 40, circlePaint);
                }
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDetachedFromWindow() {
        Log.e(TAG, "called onDetachedFromWindow");
        super.onDetachedFromWindow();

        // Convert polygon back to string.
        convertPolygons2String();

        SharedPreferences.Editor editor = UserSharedPref.initializeSharedPreferencesForCameraROI(context).edit();
        editor.putString(UserSharedPref.cameraROI, cameraROI);
        editor.apply();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.e(TAG, "called onTouch");
        canvasTouchManager.update(event);
        Vector2D vct = canvasTouchManager.getPoint();

        float minDist = 200000.0f;
        float radius = 200;

        int minIndex = -1;
        String key = "";

        for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {

            List<Vector2D> points = entry.getValue();
            for (int i = 0; i < points.size(); i++) {
                float dist = points.get(i) == null ? 0 : Vector2D.subtract(vct, points.get(i)).getLength();
                if (dist >= radius) {
                    continue;
                }

                if (dist < minDist) {
                    minDist = dist;
                    minIndex = i;
                    Log.e(TAG, "Matching x = " + points.get(i).getX() + ", y = " + points.get(i).getY());
                    key = entry.getKey();
                }
            }
        }

        if (minIndex != -1 && !key.isEmpty()) {
            polygons.get(key).set(minIndex, vct);
        } else {
            Log.e("OK2", "Touch point is too far, dist = " + minDist);
        }

        invalidate();

        return true;
    }

    private void convertPolygons2String() {
        cameraROI = "";
        for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {
            cameraROI += cameraROI.isEmpty() ? entry.getKey() + ":" : ";" + entry.getKey() + ":";
            List<Vector2D> points = entry.getValue();
            for (int i = 0; i < points.size(); i++) {
                float x = points.get(i).getX() / (float) getWidth();
                float y = points.get(i).getY() / (float) getHeight();

                cameraROI += String.format("%.2f", x);
                cameraROI += ",";
                cameraROI += String.format("%.2f", y);

                if (i < points.size() - 1) {
                    cameraROI += "|";
                }
            }
        }

        Log.e(TAG, "Converted string = " + cameraROI);
    }

    private void convertString2Polygons() {
        Log.e(TAG, "called  convertString2Polygons");
        String[] ROIs = cameraROI.split(";");
        if (cameraROI.isEmpty() || ROIs.length == 0) {
            Log.e(TAG, "No polygon is configured.");
            polygons.clear();
            return;
        }

        // Parse and add each polygon
        for (String roi : ROIs) {
            String[] polygonString = roi.split(":");
            if (polygonString.length != 2) {
                continue;
            }

            String[] vertices = polygonString[1].split("\\|");
            if (vertices.length < 3) {
                Log.d(TAG, polygonString[1] + " is not a valid polygon setting, which needs at least 3 vertices, e.g '0,5,0.1|0.3,0.4|0.5,0.6|0.7,0.8'.");
                return;
            }

            List<Vector2D> points = new ArrayList<>();
            for (String vertex : vertices) {
                Log.d(TAG, "Vertex = " + vertex);
                String[] vertexString = vertex.split(",");
                if (vertexString.length != 2) {
                    Log.d(TAG, vertex + " is not a valid vertex setting. An example should look like '0.5,0.5'.");
                    return;
                }

                try {
                    float x = Float.parseFloat(vertexString[0]);
                    float y = Float.parseFloat(vertexString[1]);

                    points.add(new Vector2D(x * getWidth(), y * getHeight()));

                    Log.d(TAG, "Adding [" + x + ", " + y + "]");
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    Log.d(TAG, vertex + " is invalid. Vertex's X and Y coordinates should be float numbers.");
                    return;
                }
            }

            polygons.put(polygonString[0], points);
            Log.d(TAG, "Add configured polygon: " + polygonString[0] + " - " + polygonString[1]);
        }
    }
}
基本上,此代码中最重要的部分是当DrawPolygonCanvas中的onDraw()出现问题时,
exampleActivity ex=newexampleActivity()
位图bm=ex.getBitmap()正在创建错误,说明:

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.graphics.drawable.drawable android.widget.ImageView.getDrawable()”

由于某种原因,XML文件中的imageView未初始化。 我如何解决这个问题

exampleActivity ex = new exampleActivity();
Bitmap bm = ex.getBitmap();
根本原因:因为您正在创建
ExampleActivity
的新实例,所以不会调用所有活动回调方法,例如
onCreate
onStart
onResume
等。在您的情况下,因为
onCreate
从未调用过,所以您的
img
总是
null
。因此,当您对其调用
getDrawable
方法时,Android将抛出一个
NullPointerException

java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable android.widget.ImageView.getDrawable()' on a null object reference.
提示:不要在Android中创建活动实例,只需在AndroidManifest.xml文件中注册活动,然后在活动回调方法中编写代码

解决方案:回到您的案例,要从活动中获取位图,您可以实现一个侦听器界面,将位图从
exampleActivity
传递到
DrawPolygonCanvas

DrawPolygonCanvas

public class DrawPolygonCanvas extends View implements OnTouchListener{

    public interface OnGetBitmapListener {
        Bitmap onGetBitmap();
    }

    private OnGetBitmapListener mOnGetBitmapListener;

    public void setOnGetBitmapListener(OnGetBitmapListener listener) {
        mOnGetBitmapListener = listener;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.e(TAG, "called onDraw");
        super.onDraw(canvas);
        paint.setFilterBitmap(true);

        // Add these lines
        Bitmap bm = null;
        if (mOnGetBitmapListener != null) {
            bm = mOnGetBitmapListener.onGetBitmap();
        }

        canvas.drawBitmap(bm, null, dest, paint);
    }
}
public class exampleActivity extends Activity implements DrawPolygonCanvas.OnGetBitmapListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        img = (ImageView) findViewById(R.id.office);

        DrawPolygonCanvas canvas = (DrawPolygonCanvas) findViewById(R.id.DrawPolygonCanvas);
        canvas.setOnGetBitmapListener(this);
    }

    @Override
    public Bitmap onGetBitmap() {
        Bitmap bm = ((BitmapDrawable) img.getDrawable()).getBitmap();
        return bm;
    }
}
示例活动

public class DrawPolygonCanvas extends View implements OnTouchListener{

    public interface OnGetBitmapListener {
        Bitmap onGetBitmap();
    }

    private OnGetBitmapListener mOnGetBitmapListener;

    public void setOnGetBitmapListener(OnGetBitmapListener listener) {
        mOnGetBitmapListener = listener;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.e(TAG, "called onDraw");
        super.onDraw(canvas);
        paint.setFilterBitmap(true);

        // Add these lines
        Bitmap bm = null;
        if (mOnGetBitmapListener != null) {
            bm = mOnGetBitmapListener.onGetBitmap();
        }

        canvas.drawBitmap(bm, null, dest, paint);
    }
}
public class exampleActivity extends Activity implements DrawPolygonCanvas.OnGetBitmapListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        img = (ImageView) findViewById(R.id.office);

        DrawPolygonCanvas canvas = (DrawPolygonCanvas) findViewById(R.id.DrawPolygonCanvas);
        canvas.setOnGetBitmapListener(this);
    }

    @Override
    public Bitmap onGetBitmap() {
        Bitmap bm = ((BitmapDrawable) img.getDrawable()).getBitmap();
        return bm;
    }
}

不要将图像存储在原始文件夹中。使用drawable folderAlso,是谁让你实例化这样的活动的
exampleActivity ex=newexampleActivity()?当然,当你这样做的时候,什么都不会起作用。我在exampleActivity中有一个方法getBitmap(),我必须调用它来实例化位图方法,我就是这样做的,有什么更好的方法吗?嘿,它是不是
公共接口OnGetBitmapListener{void bitmap onGetBitmap();}
没有void?还有
canvas.setOnGetBitmapListener(这个)
给出了一个类型错误,传递给canvas.setOnGetBitmapListener()的参数是错误的。我刚刚通过删除
void
编辑了我的答案。exampleActivity也必须实现侦听器。
canvas.setOnGetBitmapListener(此)
在DrawPolygonCanvas中存在此编译错误
setOnGetBitmapListener(com.lambdahash.sonic.example.draw.senapr.DrawPolygonCanvas.OnGetBitmapListener)无法应用于(com.lambdahash.sonic.example.exampleActivity)
OnGetBitmapListener()
无法重写。主要问题是如何在exampleActivity中设置BitmapListener而不出错?是否在
exampleActivity
中实现
OnGetBitmapListener