I'm trying to create a simple app that draws a simple figure and then after clicking the button does some affine transformation with the figure.
Can you help me finishing onClick
method rotate? Thank you a lot. The problem is that I don't know how to pass Canvas
to that method from onDraw
method in my CanvasView
, if it is possible.
MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
Button button_1;
Button button_2;
Button button_3;
Button button_4;
private CanvasView customCanvas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customCanvas = (CanvasView) findViewById(R.id.signature_canvas);
button_1 = (Button) findViewById(R.id.btn_1);
button_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customCanvas.translate();
}
});
button_2 = (Button) findViewById(R.id.btn_2);
button_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customCanvas.reflect();
}
});
button_3 = (Button) findViewById(R.id.btn_3);
button_3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customCanvas.scale();
}
});
button_4 = (Button) findViewById(R.id.btn_4);
button_4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customCanvas.rotate();//How to pass Canvas from my CanvasView to rotate method?
}
});
}
}
CanvasView.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
class CanvasView extends View {
private Paint redPaint;
private Matrix matrix;
private Path path;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
redPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
redPaint.setStyle(Paint.Style.STROKE);
redPaint.setColor(0xffff0000);
redPaint.setStrokeWidth(5);
matrix = new Matrix();
path = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.moveTo(400, 400);
path.lineTo(400, 800);
path.lineTo(800, 700);
path.lineTo(600, 600);
path.lineTo(800, 500);
path.lineTo(400, 400);
path.close();
canvas.drawPath(path, redPaint);
}
public void translate() {
}
public void reflect() {
}
public void scale() {
}
public void rotate(Canvas canvas) {
matrix.reset();
matrix.setRotate(90, 400, 400);
path.transform(matrix);
redPaint.setColor(Color.BLUE);
canvas.drawPath(path, redPaint);
}
}
Activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom">
<com.example.lab2.CanvasView
android:id="@+id/signature_canvas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"/>
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="bottom"
android:orientation="horizontal">
<Button
android:id="@+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Перенос"
android:textSize="8dp" />
<Button
android:id="@+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Отражение"
android:textSize="8dp" />
<Button
android:id="@+id/btn_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Масштабирование"
android:textSize="8dp" />
<Button
android:id="@+id/btn_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Поворот"
android:textSize="8dp" />
</LinearLayout>
</RelativeLayout>
You should not pass Canvas
into rotate
or any other functions. Everything related to modifying canvas should happen within onDraw
method.
Update your rotate()
method to invoke invalidate()
method of View
so it will be picked up by the system to be drawn for the next frame:
public void rotate() {
matrix.reset();
matrix.setRotate(90, 400, 400);
path.transform(matrix);
redPaint.setColor(Color.BLUE);
invalidate(); // Invalidated Views should be updated
}
Why invalidate()
?
If we take a look at java docs we will find the next explanation of invalidate()
method (and method body):
/**
* Invalidate the whole view. If the view is visible,
* {@link #onDraw(android.graphics.Canvas)} will be called at some point in
* the future.
* <p>
* This must be called from a UI thread. To call from a non-UI thread, call
* {@link #postInvalidate()}.
*/
public void invalidate() {
invalidate(true);
}
User contributions licensed under CC BY-SA 3.0