Java 使用;id";而不是",;安卓:id“;导致NullPointerException
我创建了一个子类Java 使用;id";而不是",;安卓:id“;导致NullPointerException,java,android,canvas,nullpointerexception,Java,Android,Canvas,Nullpointerexception,我创建了一个子类View,用于绘制三角形。下图显示了三角形绘图视图 import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.support.annotation.Nullable; import android.
View
,用于绘制三角形。下图显示了三角形绘图视图
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.support.v4.content.res.ResourcesCompat;
import android.util.AttributeSet;
import android.view.View;
public class TriangleDrawView extends View {
private Paint mPaint;
private Path mPath;
private int mDrawColor;
private int mBackgroundColor;
private Canvas mExtraCanvas;
private Bitmap mExtraBitmap;
private int paddingX, paddingY;
private int drawableRectX,drawableRectY;
private int triangleBoundX,triangleBoundY;
private int total_width,total_height;
private double angle_a,angle_b,angle_c;
private int xA,xB,xC,yA,yB,yC;
public TriangleDrawView(Context context) {
this(context,null);
}
public TriangleDrawView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mBackgroundColor = ResourcesCompat.getColor(getResources(),
R.color.opaque_orange, null);
mDrawColor = ResourcesCompat.getColor(getResources(),
R.color.opaque_yellow, null);
// Holds the path we are currently drawing.
mPath = new Path();
// Set up the paint with which to draw.
mPaint = new Paint();
mPaint.setColor(mDrawColor);
// Smoothes out edges of what is drawn without affecting shape.
mPaint.setAntiAlias(true);
// Dithering affects how colors with higher-precision device
// than the are down-sampled.
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE); // default: FILL
mPaint.setStrokeJoin(Paint.Join.ROUND); // default: MITER
mPaint.setStrokeCap(Paint.Cap.ROUND); // default: BUTT
mPaint.setStrokeWidth(5); // default: Hairline-width (really thin)
angle_a = Math.PI/3;
angle_b = Math.PI/3;
angle_c = Math.PI/3;
paddingX = 100;
paddingY = 100;
}
@Override
protected void onSizeChanged(int width, int height,
int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
// Create bitmap, create canvas with bitmap, fill canvas with color.
mExtraBitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
mExtraCanvas = new Canvas(mExtraBitmap);
// Fill the Bitmap with the background color.
mExtraCanvas.drawColor(mBackgroundColor);
total_width = width;
total_height = height;
drawTriangle(angle_a,angle_b,angle_c);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw the bitmap that stores the path the user has drawn.
// Initially the user has not drawn anything
// so we see only the colored bitmap.
canvas.drawBitmap(mExtraBitmap, 0, 0, null);
}
private void initTriangleBounds(double angle_b, double angle_c, int total_width,int total_height, int paddingX, int paddingY){
drawableRectX = total_width-2*paddingX;
drawableRectY=total_height-2*paddingY;
int x_,y_;
x_ = total_width/2;
y_ = total_height/2;
if(angle_b<Math.PI/2 && angle_c<Math.PI/2 ){
if(drawableRectX >= ( drawableRectY/Math.tan(angle_b) + drawableRectY/Math.tan(angle_c) ) ){
triangleBoundY = drawableRectY;
triangleBoundX = (int)( drawableRectY/Math.tan(angle_b) + drawableRectY/Math.tan(angle_c) );
}else{
triangleBoundX = drawableRectX;
triangleBoundY = (int) ( drawableRectX/( 1/Math.tan(angle_b) +1/Math.tan(angle_c) ) );
}
xB = x_ - triangleBoundX/2;
yB = y_ + triangleBoundY/2;
xC = x_ + triangleBoundX/2;
yC = yB;
yA = y_ - triangleBoundY/2;
xA = xB + (int)(triangleBoundY/Math.tan(angle_b));
}else if(angle_b>=Math.PI/2){
if( drawableRectX <= ( drawableRectY/Math.tan(angle_c) )){
triangleBoundY = drawableRectY;
triangleBoundX = (int)( drawableRectY/Math.tan(angle_c));
}else{
triangleBoundX = drawableRectX;
triangleBoundY = (int)( drawableRectX * Math.tan(angle_c));
}
xA = x_ - triangleBoundX/2;
yA = y_ - triangleBoundY/2;
xC = x_ + triangleBoundX/2;
yC = y_ + triangleBoundY/2;
xB = xA + (int)(triangleBoundY/Math.tan(Math.PI - angle_b));
yB = yC;
}else if(angle_c>=Math.PI/2){
if( drawableRectX <= ( drawableRectY/Math.tan(angle_b) )){
triangleBoundY = drawableRectY;
triangleBoundX = (int)( drawableRectY/Math.tan(angle_b));
}else{
triangleBoundX = drawableRectX;
triangleBoundY = (int)( drawableRectX * Math.tan(angle_b));
}
xA = x_ + triangleBoundX/2;
yA = y_ - triangleBoundY/2;
xB = x_ - triangleBoundX/2;
yB = y_ + triangleBoundY/2;
xC = xA - (int)(triangleBoundY/Math.tan(Math.PI - angle_c));
yC = yB;
}
}
public void drawTriangle(double angle_a, double angle_b, double angle_c){
this.angle_a = angle_a;
this.angle_b = angle_b;
this.angle_c = angle_c;
initTriangleBounds(angle_b,angle_c,total_width,total_height,paddingX,paddingY);
mPath.moveTo(xA, yA);
mPath.quadTo(xA,yA,xB,yB);
mPath.quadTo(xB,yB,xC,yC);
mPath.quadTo(xC,yC,xA,yA);
mExtraCanvas.drawPath(mPath, mPaint);
invalidate();
}
}
当活动开始时,它工作正常,如下面的屏幕截图所示。
我需要做的是调用TriangleDrawView的方法的public void drawTriangle(双角度a、双角度b、双角度c)
。因此,在活动中按钮的onClick方法中,我调用了drawTriangle
方法,如下所示
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="my.canvas2.TestingActivity">
<view
class="my.canvas2.TriangleDrawView"
id="@+id/viewTriangle"
android:layout_width="273dp"
android:layout_height="302dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:onClick="onClick"/>
</android.support.constraint.ConstraintLayout>
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class TestingActivity extends AppCompatActivity {
private TriangleDrawView triangleDrawView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_testing);
triangleDrawView = findViewById(R.id.viewTriangle);
}
public void onClick(View view) {
double pi = Math.PI;
//Method implemented
triangleDrawView.drawTriangle(pi/2,pi/3,pi/6);
}
}
但是,当点击的按钮时,应用程序崩溃,说出现了NullPointerException
。这是LogCat输出
FATAL EXCEPTION: main
Process: my.canvas2, PID: 15645
java.lang.IllegalStateException: Could not execute method for android:onClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void my.canvas2.TriangleDrawView.drawTriangle(double, double, double)' on a null object reference
at my.canvas2.TestingActivity.onClick(TestingActivity.java:24)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
更新
有问题的NullPointerException
解释得很好。但这并没有解决我的问题。通过和的回答,我成功地解决了这个问题
元素上的id属性必须具有android前缀。
也就是说,android:id=“@+id/viewTriangle”。如果你的IDE
至少没有就此发出警告
-
您的视图triangleDrawView未初始化,因为您使用
元素上的XML中的id属性,这就是
.findViewById(id)无法正确查找和初始化视图
正在更改id=。。。到android:id=。。。应该能解决你的问题
-您的视图triangleDrawView
未被初始化,因为您在
元素的XML
中使用了id
属性,这就是.findViewById(id)
无法正确查找和初始化视图的原因
将id=…
更改为android:id=…
应该可以解决您的问题。您的视图triangaledrawview
未被初始化,因为您在
元素上的XML
中使用了id
属性,这就是.findViewById(id)的原因
无法正确查找和初始化您的视图
将id=…
更改为android:id=…
应该可以解决您的问题。使用调试来纠正此问题。某些值为null,因此它给出了null指针异常。在drawTraingle()方法中添加调试断点,并检查哪个值为null。使用调试纠正此问题。某些值为null,因此它给出了null指针异常。在drawTraingle()方法中添加调试断点,并检查哪个值为null。元素上的id
属性必须具有android
前缀。也就是说,android:id=“@+id/viewTriangle”
。如果你的IDE没有给出至少一个警告,我会感到惊讶。这个问题很好地解释了@akhilesh0707的可能重复的NullPointerException。但是它没有解决我的问题。
元素上的id
属性必须具有android
前缀。也就是说,android:id=“@+id/viewTriangle”
。如果你的IDE没有给出至少一个警告,我会感到惊讶。这个问题很好地解释了@akhilesh0707的可能重复的NullPointerException。但这并没有解决我的问题。