How can I draw with canvas over an xml background? - java

I'm working on a simple project for my studies and I’m stuck with this problem.
I'm building Snakes And Ladders app and I’m trying to make my player (PNG image) to move around the board an animate.
I want the animation to happen over the game’s board background which I defined in an xml file and I just can’t do it.
The program that I will attach is not working, I have no idea why. In addition I need to add the part that takes the xml background in consideration, that part is missing and I will greatly appreciate if someone can help me solve this problem.
Thanks in advanced.
The board xml file(game.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/easymap"
android:orientation="vertical" >
<TextView
android:id="#+id/whitePlayer"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#drawable/white"
android:visibility="gone" />
<TextView
android:id="#+id/blackPlayer"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#drawable/black"
android:visibility="gone" />
<Button
android:id="#+id/btRoll"
android:layout_width="160dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignTop="#+id/cubePic"
android:background="#drawable/buttonshape"
android:text="Roll"
android:textColor="#FFFFFF" />
<TextView
android:id="#+id/cubePic"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="42dp"
android:layout_marginRight="22dp"
android:background="#drawable/cube" />
<TextView
android:id="#+id/tvTurn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/cubePic"
android:layout_alignRight="#+id/btRoll"
android:text="Your turn!"
android:textColor="#color/green"
android:textSize="32dp"
android:textStyle="italic" />
</RelativeLayout>
The java class:
package com.example.snakesnladders;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class GFX_Game extends Activity implements OnClickListener {
TextView whitePlayer, blackPlayer;
Button roll;
TextView cube, map1, map2, map3, label;
boolean yourTurn = true;
MyBringBack ourView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ourView = new MyBringBack(this);
setContentView(ourView);
init();
}
private void init() {
cube = (TextView) findViewById(R.id.cubePic);
roll = (Button) findViewById(R.id.btRoll);
label = (TextView) findViewById(R.id.tvTurn);
roll.setOnClickListener(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
public void onClick(View view) {
int rand = (int) (Math.random() * 6) + 1;
}
class MyBringBack extends SurfaceView implements Runnable {
SurfaceHolder ourHolder;
Thread ourThread = null;
Bitmap backGround, playerB, playerW;
boolean isRunning = true;
public MyBringBack(Context context) {
super(context);
playerW = BitmapFactory.decodeResource(getResources(),
R.id.whitePlayer);
ourHolder = getHolder();
ourThread = new Thread(this);
ourThread.start();
}
#Override
public void run() {
while (isRunning) {
if (!ourHolder.getSurface().isValid())
continue;
Canvas canvas = ourHolder.lockCanvas();
canvas.drawBitmap(playerW, 0, 0, null);
ourHolder.unlockCanvasAndPost(canvas);
}
}
}
}
The changed inner class:( I've extended View an override the onDraw method from the Viev class, and it still not working)
In addition I wanted to draw on my existing xml layout that i created in the game.xml file.
class MyBringBack extends View {
Bitmap playerW;
public MyBringBack(Context context) {
super(context);
playerW = BitmapFactory.decodeResource(getResources(),
R.id.whitePlayer);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawBitmap(playerW,0,0,null);
}
}

Create a custom View as follows. If you're root view is RelativeLayout and you need to draw on it, extend a RelativeLayout
public final class MyRelativeLayout extends RelativeLayout {
Bitmap playerW;
public MyRelativeLayout(Context context) {
super(context);
init(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs, int style) {
super(context, atts, style);
init(context);
}
private void init(final Context context) {
playerW = BitmapFactory.decodeResource(context.getResources(),
R.id.whitePlayer);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(playerW,0,0,null);
}
}
Then use it in xml as follows
<?xml version="1.0" encoding="utf-8"?>
<your.package.name.package.MyRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
all the stuff here
<your.package.name.package.MyRelativeLayout>

Related

Android - How do I add button from code on top of canvas. I don't have layout to grab

I've got an app that works like Paint. Everything works fine but what I want to do is adding couple buttons, that would change my "brush" color and width. But since I don't have xml file, I got no idea how to do that. I know that I can do something like this : container.addView(button) but I don't have layout to grab and add button to. At least I don't know how to do that.
Here is my code:
public class Paint extends Activity {
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PaintView paintView = new PaintView(this);
setContentView(paintView);
}
}
PaintView class:
package com.example.centrummultimedialne;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
public class PaintView extends View {
public LayoutParams params;
private Path path = new Path();
private Paint brush = new Paint();
public PaintView(Context context) {
super(context);
brush.setAntiAlias(true);
brush.setColor(Color.MAGENTA);
brush.setStyle(Paint.Style.STROKE);
brush.setStrokeJoin(Paint.Join.ROUND);
brush.setStrokeWidth(8f);
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX, pointY);
break;
default:
return false;
}
postInvalidate();
return false;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, brush);
}
}
I suggest you to use a xml layout. It's a lot easier.
main.xml //Put this inside src/main/res/layout/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.centrummultimedialne.PaintView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_weight="1.0"
android:id="#+id/paintView"/>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Color"
android:layout_weight="1.0"
android:id="#+id/btn1"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Stroke"
android:layout_weight="1.0"
android:id="#+id/btn2"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Button"
android:layout_weight="1.0"
android:id="#+id/btn3"/>
</LinearLayout>
</LinearLayout>
Change setContentView(paintView); in Paint class to setContentView(R.layout.main);
Modify your PaintView's constructors to accept external layout.
public PaintView(Context context)
{
super(context, null);
init(context);
}
public PaintView(Context context, AttributeSet attrs)
{
super(context, attrs, 0);
init(context);
}
public PaintView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr, 0);
init(context);
}
public PaintView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init()
{
brush.setAntiAlias(true);
brush.setColor(Color.MAGENTA);
brush.setStyle(Paint.Style.STROKE);
brush.setStrokeJoin(Paint.Join.ROUND);
brush.setStrokeWidth(8f);
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
Later in Paint class, set all these buttons a listener.
public class MainActivity extends Activity implements View.OnClickListener
{
PaintView paintView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
paintView = findViewById(R.id.paintView);
((Button)findViewById(R.id.btn1)).setOnClickListener(this);
((Button)findViewById(R.id.btn2)).setOnClickListener(this);
((Button)findViewById(R.id.btn3)).setOnClickListener(this);
}
#Override
public void onClick(View btn)
{
switch(btn.getId()) {
case R.id.btn1: paintView.changeColor(Color.BLUE); break;
case R.id.btn2: paintView.setStroke(10F); break;
}
}
}
Now in PaintView class, you can implement changeColor(int Color) or any other methods you like.

restrict a custom view in a relative layout

I am new to android and I am a bit stuck. I am trying to create a simple drawing app which shows an example on the top of the page and a square space for it in below it. Aim is to display a letter and a kid needs to practice in replicating it.
I have troubles including the drawing class in the layout which needs to restrict its boundaries.
this is the main layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".MainActivity">
<TextView
android:id="#+id/exampleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
enter code here` android:id="#+id/drawingBoard"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/exampleText">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
this is the PaintView class
import android.app.ActionBar;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
public class PaintView extends View {
public ViewGroup.LayoutParams param;
private Path path = new Path();
private Paint brush = new Paint();
public PaintView(MainActivity context) {
super(context);
brush.setAntiAlias(true);
brush.setColor(Color.RED);
brush.setStyle(Paint.Style.STROKE);
brush.setStrokeJoin(Paint.Join.ROUND);
brush.setStrokeWidth(8f);
param = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX,pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX,pointY);
break;
default:
return false;
}
postInvalidate();
return false;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path,brush);
}
this is how it is called in the Main Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PaintView paintView = new PaintView(this);
setContentView(paintView);
}
I need to fit the drawing board into the "drawingBoard".
It is not necessary the right approach, but this is as far as I got.
Thanks in advance
Attach the customview to a fragment.
This is a completely different approach so you will have to make a lot of changes to your code.
The other approach would be adding the view programmatically to the ConstraintLayout.
In MainActivity,
protected void onCreate(Bundle savedInstanceStatee) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//remove those lines.
/*
PaintView paintView = new PaintView(this);
setContentView(paintView);*/
ConstraintLayout parentLayout = (ConstraintLayout)findViewById(R.id.drawingBoard);
ConstraintSet set = new ConstraintSet();
PaintView paintView = new PaintView(this);
// set view id, else getId() returns -1
paintView.setId(View.generateViewId());
layout.addView(paintView, 0);
set.clone(parentLayout);
// connect start and end point of views, in this
case top of child to top of parent.
set.connect(paintView.getId(),
ConstraintSet.TOP,parentLayout.getId(),
ConstraintSet.TOP, 60);
// ... similarly add other constraints
set.applyTo(parentLayout);
}
In the activity you are overwriting the content view with just the paint view:
setContentView(paintView);
Remove that line.
Add the PaintView in XML instead:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".MainActivity">
<TextView
android:id="#+id/exampleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- TODO: Replace with your package name -->
<com.example.PaintView
android:id="#+id/drawingBoard"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/exampleText" />
</androidx.constraintlayout.widget.ConstraintLayout>
With this approach you have to inflate the custom view in its constructors:
public class PaintView extends ConstraintLayout {
public PaintView(#NonNull Context context) {
super(context);
init();
}
public PaintView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public PaintView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public PaintView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public void init() {
inflate(getContext(), R.layout.layout_product_item, this);
}
}
To interact with the PaintView from the activity code you can do:
PaintView paintView = (PaintView) findViewById(R.id.drawingBoard);

Rotating path outside onDraw Method

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);
}

Drawing Circles using Canvas and Framelayout android

I am trying to create an app that displays a circle everytime I click a button. I have the layout looking great but when i click the button(circle) to display a circle on the screen nothing happens. I'm not confident that my draw circle class is being called correctly in my main activity. Here is my code below.
package com.example.randomcircles;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
public class DisplayRandomCircles extends Activity
{
DrawCircle c;
Canvas d;
#Override
public void onCreate(Bundle b)
{
super.onCreate(b);
setContentView(R.layout.activity_display_random_circles);
Button btn1 = (Button) findViewById(R.id.btn1);
Button btn2 = (Button) findViewById(R.id.btn2);
c = new DrawCircle(getApplicationContext());
d = new Canvas();
FrameLayout f1 = (FrameLayout) findViewById(R.id.frame);
}
#SuppressLint("WrongCall")
public void doit(View v)
{
switch (v.getId())
{
case (R.id.btn1):
c.onDraw(d);
break;
case (R.id.btn2):
break;
}
}
}
Here is my DrawCircle class
package com.example.randomcircles;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawCircle extends View
{
public DrawCircle(Context con)
{
super(con);
}
#Override
protected void onDraw(Canvas c)
{
super.onDraw(c);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setAntiAlias(true);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(100);
p.setColor(Color.RED);
p.setStyle(Paint.Style.FILL);
c.drawCircle(75, 75, 100, p);
}
}
And my layout xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight=".75"
android:orientation="vertical" >
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".25"
android:gravity="bottom|center"
android:orientation="horizontal" >
<Button
android:id="#+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:layout_weight=".50"
android:onClick="doit"
android:text="#string/Circle" />
<Button
android:id="#+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".50"
android:layout_gravity="end|bottom"
android:onClick="doit"
android:text="#string/Clear" />
</LinearLayout>
</LinearLayout>
Ok, here are some changes I'd make for this. I'm not exactly sure what you're trying to do, but this should make things easier.
First, change your class "DrawCircle" like this:
public class DrawCircle extends View
{
final Paint circlePaint;
{
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setAntiAlias(true);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(100);
circlePaint.setColor(Color.RED);
circlePaint.setStyle(Paint.Style.FILL);
}
public DrawCircle(Context con)
{
super(con);
}
public DrawCircle(Context con, AttributeSet set)
{
super(con, set);
}
public DrawCircle(Context con, AttributeSet set, int style)
{
super(con, set, style);
}
#Override
protected void onDraw(Canvas c)
{
super.onDraw(c);
c.drawCircle(75, 75, 100, circlePaint);
}
}
This will allow you to reuse the same Paint object with each draw because the onDraw() method can be called hundreds of times and there's no need to slow down your program for this.
Second, adding the other constructors allows you to add the View to your FrameLayouts by xml.
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.randomCircles.DrawCircle
android:id="#+id/circleFrame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Next, to fill your screen, you need to loop in your onDraw method. Think about drawing on the canvas as a stamp. Every time you draw, you stamp your image at the location you specify on top of the previous draw.
So
protected void onDraw(Canvas c)
{
super.onDraw(c);
for(int i = 0; i < 10; i++)
{
c.drawCircle(i*100, 75, 100, circlePaint);
}
}
This should draw 10 circles of radius 100 pixels across the top of your screen.

how do you have 3 layers(layouts or objects) in an android app?

I have been trying to figure out how have a background layout with 2 more layers on top. When an imageView (person) is tapped, I want it to become a part of the boat, drawn on top of the boat. This way, when the boat imageView is tapped, the person will move with the boat across the river. I have the boat moving back and forth when tapped, but want to set the person imageView to be like a child of the boat imageView when tapped on. Right now I'm working on just getting the person to become a child of the boat imageView, but everything I have been trying just compiles, runs, and then displays everything in the right place except the person imageView is at the top left instead of inside the boat. If someone could point out to me what I'm doing wrong and what the best way is to have multiple layers like this, I would appreciate it.
There are no errors, the person object just doesn't show up in the boat.
Here is the main activity:
package com.cannibal_photographer;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout main = (FrameLayout)findViewById(R.layout.activity_main);
LayoutInflater li = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup boatview = (ViewGroup) li.inflate(R.layout.boatlayout,main,false);
View personview = li.inflate(R.layout.personlayout,boatview,false);
((ViewGroup) main).addView(boatview);
((ViewGroup) boatview).addView(personview);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Here is the Boat class:
package com.cannibal_photographer;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
public class Boat extends ImageView {
boolean state = true;
public Boat(Context context) {
super(context);
init();
}
public Boat(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public Boat(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
private void init()
{
this.setOnClickListener(new OnClickListener() {
#Override
public void onClick (View v) {
if (state) {
moveBoat(-215);
} else {
moveBoat(215);
}
}
});
}
//TranslateAnimation animation;
//TranslateAnimation animation2;
public void moveBoat(int amount){
/*
animation = new TranslateAnimation(0, 0, 0, amount);
animation.setDuration(250);
animation.setFillAfter(true);
this.startAnimation(animation);
*/
this.offsetTopAndBottom(amount);
state = !state;
}
}
Here is the person class:
package com.cannibal_photographer;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
public class Person extends ImageView {
boolean state = true;
public Person(Context context) {
super(context);
init();
}
public Person(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public Person(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
private void init()
{
this.setOnClickListener(new OnClickListener() {
#Override
public void onClick (View v) {
if (state) {
//movePerson(325,-230);
} else {
//movePerson(-325,230);
}
}
});
}
public void movePerson(int x, int y)
{
this.offsetLeftAndRight(x);
this.offsetTopAndBottom(y);
state = !state;
}
}
Here is the main layout for the background:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#layout/activity_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
</FrameLayout>
Here is the boat layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/framelayoutView"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.cannibal_photographer.Boat
android:id="#+id/boatimageView"
android:layout_width="78dp"
android:layout_height="130dp"
android:layout_marginLeft="105dp"
android:layout_marginTop="225dp"
android:src="#drawable/boat" />
</FrameLayout>
And finally, here is the person layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.cannibal_photographer.Person
android:id="#+id/personView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/greensquare"
android:gravity="center_vertical" />
</FrameLayout>

Categories

Resources