I would like to build an application where user can build his own path using buttons. I have problems with updating X and Y coordinates, basically i don't know how can i make it. What i have done so far - lines are drawing in the same point because my coordinates are not updating yet. I made some tests with get and set methods but my thinking was not correct so i did not put this in a code to avoid errors. What i want to achieve: lines got two points - starting point and ending point, when i press the button, line is drawing on canvas, when i press another button, another line should be drawn but not in the same coordinates as the first one but in ending point of previous one etc.
For example:
when i press top button:
canvas.drawLine(300,300,300, 250,paint);
when i press right button:
canvas.drawLine(300,250,350, 250,paint);
when i press top button again:
canvas.drawLine(350,250,350, 200,paint);
Ending point of one line should be starting point of another one and button click adding or substracting value 50 to X or Y coordinate depending on the direction.
I am adding screens showing how it works now and how i would like to make it. I am looking for any help or tips.
Buttons right and left are in wrong places but it is not important here
public class MainActivity extends ActionBarActivity {
Button top;
Button bottom;
Button left;
Button right;
Button clear;
ImageView img;
int x=300;
int y=300;
int x1=300;
int y1=300;
Integer gettingX() {
return x;
}
void settingX(Integer x) {
this.x = x;
}
Integer gettingY() {
return y;
}
void settingY(Integer y) {
this.y = y;
}
Integer gettingY1() {
return y1;
}
void settingY1(Integer y1) {
this.y1 = y1;
}
Integer gettingX1() {
return x1;
}
void settingX1(Integer x1) {
this.x1 = x1;
}
Paint paint = new Paint();
Bitmap bmp = Bitmap.createBitmap(600, 600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.img);
top = (Button) findViewById(R.id.top);
bottom = (Button) findViewById(R.id.bottom);
left = (Button) findViewById(R.id.left);
right = (Button) findViewById(R.id.right);
clear = (Button) findViewById(R.id.clear);
top.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(25);
canvas.drawLine(x,y,x1, y1-50,paint);
img.setImageBitmap(bmp);
}
});
bottom.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(25);
canvas.drawLine(x,y,x1, y1+50,paint);
img.setImageBitmap(bmp);
}
});
left.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(25);
canvas.drawLine(x,y,x1-50, y1,paint);
img.setImageBitmap(bmp);
}
});
right.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(25);
canvas.drawLine(x,y,x1+50, y1,paint);
img.setImageBitmap(bmp);
}
});
clear.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
canvas.drawColor(Color.WHITE);
img.setImageBitmap(bmp);
}
});
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res
/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/top"
android:text="top"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right"
android:id="#+id/right"
android:layout_gravity="right"
android:layout_alignTop="#+id/left"
android:layout_toLeftOf="#+id/bottom"
android:layout_toStartOf="#+id/bottom" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left"
android:id="#+id/left"
android:layout_below="#+id/top"
android:layout_toRightOf="#+id/top"
android:layout_toEndOf="#+id/top" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bottom"
android:id="#+id/bottom"
android:layout_gravity="center_horizontal"
android:layout_below="#+id/right"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clear"
android:id="#+id/clear"
android:layout_gravity="center_horizontal"
android:layout_below="#+id/bottom"
android:layout_alignRight="#+id/bottom"
android:layout_alignEnd="#+id/bottom" />
<ImageView
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="#+id/img"
android:layout_gravity="center_horizontal"
android:layout_below="#+id/clear"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
The problem is that your code never updates the values of your x or y variables when you click the button.
First, delete these two variables:
int x1=300;
int y1=300;
and delete all of these methods:
Integer gettingX() { ... }
void settingX(Integer x) { ... }
Integer gettingY() { ... }
void settingY(Integer y) { ... }
Integer gettingY1() { ... }
void settingY1(Integer y1) { ... }
Integer gettingX1() { ... }
void settingX1(Integer x1) { ... }
Next, update all of your references to x1 or y1 to just use x and y. For example:
canvas.drawLine(x, y, x, y - 50, paint);
Finally, save the "new" values to x or y after drawing the line:
y -= 50;
Here's the updated code for your "top" button's click listener:
top.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(25);
canvas.drawLine(x, y, x, y - 50, paint);
img.setImageBitmap(bmp);
y -= 50;
}
});
Related
I have an activity in which there are 3 checkboxes in different views. These checkboxes are to pick up a color.
In the DrawingView class, I have to draw on my canvas with the color that is checked. What I want is to pass an integer value from the activity to the view class and set the color of paint accordingly. itried using getter and setters, but I get black color. I suppose this is because the color is being set in the constructor itself, and it does not change when I check any box.
Please refer this for updates in the below code
Code:
MainActivity: the color/checkbox is selected here. And the drawing is to be done in the layout of this activity itself.
carImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
drawingView=new DrawingView(carImageView.getContext());
drawingView=new DrawingView(carImageView.getContext(),null);
drawingView.setColor(color);
return false;
}
});
scratchesCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b)
{
color=1;
chipsCb.setChecked(false);
dentsCb.setChecked(false);
}
}
});
chipsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b)
{
color=2;
scratchesCb.setChecked(false);
dentsCb.setChecked(false);
}
}
});
dentsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b)
{
color=3;
chipsCb.setChecked(false);
scratchesCb.setChecked(false);
}
}
});
}
View Class:
public DrawingView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
mPaint=new Paint();
if(color==1)
mPaint.setColor(Color.RED);
else if(color==2)
mPaint.setColor(Color.BLUE);
else if(color==3)
mPaint.setColor(Color.GREEN);
this.context=context;
mPath=new Path();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.MITER);
mPaint.setStrokeWidth(5f);
}
public void setColor(int color){
this.color=color;
}
public int getColor(){
return this.color;
}
Edit
I don't necessarily want to use the exact same code. All I want is to change paint color when a checkbox is selected to be able to draw on an image view. Any other approach is welcome.
In the MainActivity, you are creating a DrawingView that has no relationship to your image view that is displayed. So, when you change the color, you are not changing the color of the displayed image view but of the unconnected DrawingView. The image view never has a new color defined and always defaults to black.
Here is a video of a small working app based upon your most recently supplied code. Maybe all the colors shouldn't change when a new check box is clicked, but you will be able to address that issue separately.
Changes I have made to the Java code are commented as such. Changes were also made to the XML to allow your code to run in my environment, but those changes were not commented.
MainActivity.java (Updated)
public class MainActivity extends AppCompatActivity {
ImageView caricon;
int itemSelected = 0;
private DrawingView carImageView;
Bitmap bitmap;
ImageView backarrow;
TextView nextcheckinAB2;
Bitmap bmp;
public static int color;
CheckBox scratchesCb, chipsCb, dentsCb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
carImageView = (DrawingView) findViewById(R.id.carImageView);
scratchesCb = (CheckBox) findViewById(R.id.scratchesCheckBox);
chipsCb = (CheckBox) findViewById(R.id.ChipCheckbx);
dentsCb = (CheckBox) findViewById(R.id.DentsCheckBox);
// Change: Make sure to initialize the color
color = 1;
carImageView.setColor(color);
carImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// drawingView = new DrawingView(carImageView.getContext(),null);
carImageView.setColor(color);
return false;
}
});
scratchesCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b) {
color = 1;
carImageView.clearCanvas();
carImageView.setColor(1); //
chipsCb.setChecked(false);
dentsCb.setChecked(false);
}
}
});
chipsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b) {
color = 2;
carImageView.setColor(2);
scratchesCb.setChecked(false);
dentsCb.setChecked(false);
}
}
});
dentsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b) {
color = 3;
// Change: Do like the other check boxes althogh not really needed.
carImageView.setColor(3);
chipsCb.setChecked(false);
scratchesCb.setChecked(false);
}
}
});
}
}
DrawingView.java (Updated)
public class DrawingView extends android.support.v7.widget.AppCompatImageView {
private Path mPath;
private Paint mPaint;
private float mX, mY;
private static final float TOLERANCE = 5;
int color;
Context context;
public DrawingView(Context context) {
super(context);
this.context = context;
init();
}
public DrawingView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public void init() {
mPath = new Path();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.MITER);
mPaint.setStrokeWidth(5f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPaint);
}
public void setColor(int color) {
if (color == 1) {
mPaint.setColor(Color.RED);
this.color = color;
invalidate();
} else if (color == 2) {
mPaint.setColor(Color.BLUE);
this.color = color;
invalidate();
} else if (color == 3) {
mPaint.setColor(Color.GREEN);
this.color = color;
invalidate();
}
}
public int getColor() {
return this.color;
}
private void onStartTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (mX + x) / 2, (mY + y) / 2);
mX = x;
mY = y;
}
}
public void clearCanvas() {
mPath.reset();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
invalidate();
}
private void upTouch() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
onStartTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
}
return true;
}
}
activity_main.xml (Updated)
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="horizontal"
android:weightSum="3">
<HorizontalScrollView
android:id="#+id/horizontalSrollView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="5dp"
android:weightSum="2">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="2dp"
android:layout_weight="0.5"
android:background="#android:color/holo_red_light" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_weight="1.5"
android:text="Scratches"
android:textColor="#000" />
</LinearLayout>
<CheckBox
android:id="#+id/scratchesCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:checked="true" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="5dp"
android:weightSum="2">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="2dp"
android:layout_weight="0.5"
android:background="#android:color/holo_blue_light" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_weight="1.5"
android:text="Chips"
android:textColor="#000" />
</LinearLayout>
<CheckBox
android:id="#+id/ChipCheckbx"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="5dp"
android:weightSum="2">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="2dp"
android:layout_weight="0.5"
android:background="#android:color/holo_green_light" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_weight="1.5"
android:text="Dings/Dents"
android:textColor="#000" />
</LinearLayout>
<CheckBox
android:id="#+id/DentsCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="8.7">
<[your package name].DrawingView
android:id="#+id/carImageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:src="#mipmap/ic_launcher"
android:layout_gravity="center_vertical" />
<!--<ImageView
android:id="#+id/carImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"/>-->
</LinearLayout>
</LinearLayout>
you need change function setColor.
1.change mPaint color.
2.add invalidate() for redraw view.
public void setColor(int color){
this.color=color;
mPaint.setColor(color);
invalidate();
}
You need to call invalidate() on the View to make it update.
Try this,
final DrawingView drawingView = new DrawingView(carImageView.getContext());
carImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
drawingView.setColor(color);
return false;
}
});
scratchesCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b)
{
color = 1;
drawingView.setColor(color);
chipsCb.setChecked(false);
dentsCb.setChecked(false);
}
}
});
chipsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b)
{
color = 2;
drawingView.setColor(color);
scratchesCb.setChecked(false);
dentsCb.setChecked(false);
}
}
});
dentsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b)
{
color = 3;
drawingView.setColor(color);
chipsCb.setChecked(false);
scratchesCb.setChecked(false);
}
}
});
DrawingView.java
public DrawingView(Context context) {
super(context);
this.context = context;
init();
}
public DrawingView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
this.context=context;
init();
}
private void init() {
mPath=new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.MITER);
mPaint.setStrokeWidth(5f);
setColor(color);
}
public void setColor(int color){
this.color=color;
if(color==1)
mPaint.setColor(Color.RED);
else if(color==2)
mPaint.setColor(Color.BLUE);
else if(color==3)
mPaint.setColor(Color.GREEN);
// Call invalidate
invalidate();
}
Define static data member in your DrawingView
static int color = 1; //default
Then, from your activity simply call
DrawingView.color = someValue;
Static Keyword before variable color will make sure there is only one variable reference for all objects of your DrawingView class.
"even if I pass a static value, say 3 in main activity in drawingview.setColor(int) it gives black. This means the setColor function in Drawingview isn't working. "
Does this mean it will call paint.setColor(3) ?
If yes, this will of course turn your color black. Try passing Color.GREEN instead
This will be my first question, so I apologize for my probable mistakes.
I'm trying to add a red circle each time I press the button I've incorported to my layout. I'd like all circles stayed in the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/panelJuego"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.76"
android:orientation="horizontal" >
</LinearLayout>
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="botonRojo"
android:text="Button" />
</LinearLayout>
The java code related with my trying is:
public void botonRojo(View v) {
LinearLayout panelJuego = (LinearLayout) findViewById(R.id.panelJuego);
PonCirculo circulo = new PonCirculo(this, 30, 30, "#FF0000");
circulo.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
panelJuego.addView(circulo);
}
public class PonCirculo extends View {
private int radio = 30;
private String color;
public PonCirculo(Context context, int x, int y, String color) {
super(context);
Cx = Cx + x;
Cy = Cy + y;
this.color = color;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor(color));
canvas.drawCircle(Cx, Cy, radio, paint);
}
Actually each time I press the button a red filled circle appears in the android screen but when I press the button again a new circle appears and the fomer disappears. Can anyone help me? Thanks.
I'm assuming you are just trying to add each circle under each other when the button is pressed.
Currently you are adding a new view each time now but it is over-laying the previous view. You need add the views giving each new circle a unique id. Then place the new circle underneath or whatever position you choose. I'm giving you some example code that I changed to use a relative layout and I place each circle under the previous one. This should get you started with what you are looking for:
Example Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/relativeCircleLayout">
</RelativeLayout>
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Circle"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:onClick="botonRojo"/>
</RelativeLayout>
Example Code:
public class MainActivity extends AppCompatActivity {
ArrayList<PonCirculo> viewList = new ArrayList<PonCirculo>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void botonRojo(View v) {
RelativeLayout panelJuego = (RelativeLayout) findViewById(R.id.relativeCircleLayout);
PonCirculo circulo = new PonCirculo(this, 30, 30, "#FF0000");
circulo.setId(View.generateViewId());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
if(!viewList.isEmpty()) {
int id = viewList.get(viewList.size()-1).getId();
params.addRule(RelativeLayout.BELOW, id);
}
panelJuego.addView(circulo, params);
viewList.add(circulo);
}
public class PonCirculo extends View {
private int radio = 30;
private String color;
int Cx, Cy;
public PonCirculo(Context context, int x, int y, String color) {
super(context);
Cx = Cx + x;
Cy = Cy + y;
this.color = color;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor(color));
canvas.drawCircle(Cx, Cy, radio, paint);
}
}
}
ObjectAnimator.ofFloat(Object target, String xPropertyName, String yPropertyName, Path path) seems to work in API 21 but not 23?
Simple reproduction: Here's the activity and layout. Try long press on the text view, both level will work. But, just tap on the view: 21 works but not 23.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View hello = findViewById(R.id.hello);
final Path p = new Path();
p.addCircle(-200, 0, 100, Path.Direction.CW);
hello.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ObjectAnimator a = ObjectAnimator.ofFloat(hello, "translationX", "translationY", p);
a.setDuration(1000);
a.start();
}
});
hello.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
ObjectAnimator a = ObjectAnimator.ofFloat(hello, "scaleX", 2);
a.setDuration(1000);
a.start();
return true;
}
});
}
}
--
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="letstwinkle.com.pathtest.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="63dp"
android:layout_marginTop="210dp"
android:id="#+id/hello"
android:background="#880033"/>
</RelativeLayout>
This may be the same as this bug reported in June. https://code.google.com/p/android/issues/detail?id=212776
As a workaround, you can use a ValueAnimator with a custom AnimatorUpdateListener.
First you need a PathMeasure for your Path. This will give you access to data like path length and coordinates on the path for a specific distance (0 <= distance <= path length).
Path p = new Path();
p.addCircle(-200, 0, 100, Path.Direction.CW);
PathMeasure pathMeasure = new PathMeasure(p, true);
Then you set the ValueAnimator to animate from 0 to the path length.
final ValueAnimator a = ValueAnimator.ofFloat(0,pathMeasure.getLength());
a.setDuration(1000);
Next, you add an AnimatorUpdateListener to actually manipulate the View. I'll show first how to add it:
MyAnimatorUpdateListener myListener = new MyAnimatorUpdateListener(hello, pathMeasure);
a.addUpdateListener(myListener);
Continue with the OnClickListener:
hello.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
a.start();
}
});
Please note that I changed the code and declared/ initialized the ValueAnimator outside of the OnClickListener to get a better performance: this way, it will not be newly created each time I click the TextView and so the garbage collector will be less busy :).
Finally, the AnimatorUpdateListener code:
class MyAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener
{
private View view;
private PathMeasure pathMeasure;
private float[] coordinates = new float[2];
public MyAnimatorUpdateListener(View view, PathMeasure pathMeasure)
{
this.view = view;
this.pathMeasure = pathMeasure;
}
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float distance = (float) animation.getAnimatedValue();
pathMeasure.getPosTan(distance, coordinates, null);
view.setTranslationX(coordinates[0]);
view.setTranslationY(coordinates[1]);
}
}
what I want to do is to add a custom view to my activity and freely drag and drop it wherever I want to. I create a new class "Square". When I construct a new Square it is displayed in the upper left Corner of the Display. When I set X and Y coordinates it disappears. If I set X and Y to 30 I see that the Square is displayed partiatelly. So it seems that my view is only displayed in a small Frame on the top Left of the Display.
Please help me to move my custom view oder the Display. Thanks!
MainActivity:
private Button btnNewSquare;
private RelativeLayout relativeLayout;
private Square[] square = new Square[10];
int squareId = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnNewSquare = (Button)findViewById(R.id.button1);
relativeLayout = (RelativeLayout)findViewById(R.id.RelativeLayout);
btnNewSquare.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v == btnNewSquare) {
squareId++;
square[squareId] = new Square(this);
square[squareId].setX(30);
square[squareId].setY(30);
square[squareId].setOnTouchListener(square[squareId]);
relativeLayout.addView(square[squareId]);
relativeLayout.invalidate();
Toast.makeText(getApplication(), "Square" + squareId, Toast.LENGTH_SHORT).show();
square[squareId].invalidate();
}
}
Square
private int squareWidth = 100;
private Paint paint;
public Square(Context context) {
super(context);
initSquare();
// TODO Auto-generated constructor stub
}
public Square(Context context, AttributeSet attrs) {
super(context, attrs);
initSquare();
}
private final void initSquare() {
paint = new Paint();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(squareWidth, squareWidth);
}
#Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
paint.setStyle(Style.FILL);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
canvas.drawRect(getX(), getY(), getX() + squareWidth, getY() + squareWidth, paint);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
v.setVisibility(View.VISIBLE);
}
return false;
}
My XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/RelativeLayout"
tools:context="${relativePackage}.${activityClass}" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="38dp"
android:text="New Square" />
</RelativeLayout>
The answer is simple. The coordinates in the onDraw() method are belonging to the view, not to the Screen. So if I move my view via Drag and Drop to let's say (500, 500) I have to draw my rectangle in the onDraw method still at (0,0,100,100) and not at (500, 500, 600, 600) so the correct line of code would be:
canvas.drawRect(0, 0, squareWidth, squareWidth, paint);
and not
canvas.drawRect(getX(), getY(), getX() + squareWidth, getY() + squareWidth, paint);
i am working on application in which my ondraw method is not working properly ......
in my applicationi am using framelayout ...
so i am used three class...
1)acticvity
2) image choosing
3) drawing
my image selection is working fine but my drawing class is not working fine ..it is not displaying any thing ....
my drawing class is as follow ...
public class Draw extends View {
String info = "";
float x = 0;
float y = 0;
int color = Color.GREEN;
public Draw(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public Draw(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(color);
paint.setStrokeWidth(15);
paint.setTextSize(30);
canvas.drawLine(x-10, y, x+10, y, paint);
canvas.drawLine(x, y-10, x, y+10, paint);
canvas.drawText(info, x, y, paint);
}
public void updateInfo(String t_info, float t_x, float t_y){
info = t_info;
x = t_x;
y = t_y;
invalidate();
}
public void clearInfo(){
info = "";
x = 0;
y = 0;
invalidate();
}
}
I am calling this from my mainactivity class.but i first call it from image selecting class as follow
public class FirstImage extends ImageView implements OnTouchListener {
MotionEvent event;
int a;
Bitmap image;
String huma ="human";
String info = "human";
float x = 0; //init value
float y = 0; //init value
Animation animationFadeIn;
public FirstImage(Context context) {
super(context);
}
public FirstImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void changeImage(int id){
this.setImageResource(id);
a=id;
final Animation animationFadeout=AnimationUtils.loadAnimation(getContext(), R.anim.zoomin);
this.startAnimation(animationFadeout);
this.setOnTouchListener(this);
}
#Override
public boolean onTouch(View arg0, MotionEvent me) {
switch(me.getAction()){
case MotionEvent.ACTION_DOWN:
x=me.getX();
y= me.getY();
pageinfo(x,y);
break;
case MotionEvent.ACTION_MOVE:
x=me.getX();
y= me.getY();
pageinfo(x,y);
break;
case MotionEvent.ACTION_UP:
x=me.getX();
y= me.getY();
pageinfo(x,y);
break;
case MotionEvent.ACTION_OUTSIDE:
x=me.getX();
y= me.getY();
pageinfo(x,y);
break;
default: return true;
}
return false;
}
public void pageinfo(float x, float y) {
// TODO Auto-generated method stub
((AshActivity)getContext()).updateMsg(info, x,y);
}
}
it is called from the main activitry class
public class AshActivity extends Activity {
ImageView i;
Draw j;
TextView t,k;
ImageButton back;
ImageButton next;
OnClickListener l2 = null;
OnClickListener l = null;
int count=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
i = (FirstImage)findViewById(R.id.image);
j=(Draw)findViewById(R.id.info);
t=(TextView)findViewById(R.id.textView);
k=(TextView)findViewById(R.id.textView1);
back=(ImageButton)findViewById(R.id.button1);
next=(ImageButton)findViewById(R.id.button2);
if (count==0){
((FirstImage) i).changeImage(R.drawable.human);
}
//addListenerOnButton();
}
public void updateMsg(String info, float x, float y) {
// TODO Auto-generated method stub
j.updateInfo(info, x, y);
}
}
my layout xml file is as folow
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:name="http://schemas.android.com/apk/res/com.example.nam"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- Screen Design for VIDEOS -->
<TableLayout
android:id="#+id/tablelayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="1">
<TableRow
android:id="#+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dip"
android:text="pic on click which will tell where is the dna located in human body or cell "
android:textSize="18dip" />
</TableRow>
<TableRow
android:id="#+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<com.example.nam.FirstImage
android:id="#+id/image"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<com.example.nam.Draw
android:id="#+id/info"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</FrameLayout>
</TableRow>
<TableRow
android:id="#+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageButton
android:id="#+id/button1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:src="#drawable/monotone_arrow_next_left"/>
<ImageButton
android:id="#+id/button2"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:src="#drawable/monotone_arrow_next_lrightcopy"/>
</LinearLayout>
</TableRow>
<TableRow
android:id="#+id/tableRow4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dip"
android:text="please don't mind "
android:textSize="18dip" />
</TableRow>
</TableLayout>
</ScrollView>
what is the problem i am not getting that ....
The problem is that your Draw instance's layout_height is 0.
This is due to the LayoutParams you've registered to it (wrap_content);
If you change the FrameLayout's attributes, the desired text will be displayed:
<FrameLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ro.rekaszeru.sample.FirstImage android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<ro.rekaszeru.sample.Draw android:id="#+id/info"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
Please also note, that the text size of 30 is very large...