我创建了一个View
的子类,用于绘制三角形。 TriangleDrawView
如下所示。
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
已包含在活动中,如下所示。
<?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>
我需要做的是调用public void drawTriangle(double angle_a, double angle_b, double angle_c)
的{{1}}方法。因此,在Activity的按钮的onClick方法中,我调用了TriangleDrawView
方法,如下所示。
drawTriangle
但是当点击按钮时,应用程序崩溃了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);
}
}
。这是LogCat输出;
NullPointerException
在this问题中对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)
进行了详细解释。但它并没有解决我的问题。我通过Mike M和Tomas Jablonskis的答案成功解决了问题。
元素上的id属性必须具有android前缀。 也就是说,android:id =“@ + id / viewTriangle”。如果您的IDE,我会感到惊讶 并没有给出至少一个警告。
- Mike M
您的视图triangleDrawView未初始化,因为您使用 元素上的XML中的id属性,这就是原因所在 .findViewById(id)无法正确查找和初始化您的视图。
将id = ...更改为android:id = ...应该可以解决您的问题。
答案 0 :(得分:1)
您的观看次数public function rules()
{
$rules = [
'guest' => 'array'
];
foreach($this->request->get('guest') as $key => $val){
$rules['guest.'.$key.'. sleeps'] = 'required|not_in:0';
$rules['guest.'.$key.'. comments'] = 'max:300';
}
return $rules;
}
尚未初始化,因为您在triangleDrawView
id
元素上使用了XML
属性,这就是<view ... >
所做的原因找不到并正确初始化.findViewById(id)
。
将View
更改为id=...
可以解决您的问题。
答案 1 :(得分:1)
使用调试来解决问题。某些值为null,因此它给出了空指针异常。在drawTraingle()方法中添加调试断点并检查哪个值为null。