Adding graphics views android layout - android

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

Related

Custom View onDraw() is being called but not appearing

SOLVED: I fixed the problem, it had to do with the constraints in my layout.
I am trying to create a custom view that for the time being simply displays a chart. This is my custom View class:
public class ChartView extends View {
private final Paint paint;
public ChartView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
setWillNotDraw(false);
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("View ", "onDraw called");
int x = getWidth();
int y = getHeight();
int divX = x / 5;
int divY = y / 7;
for (int i = 0; i <= 5; i++) {
canvas.drawLine(divX * i, 0, divX * i, y, paint);
Log.d("View", "line drawn");
}
for (int i = 0; i <= 7; i++) {
canvas.drawLine(0, divY * i, x, divY * i, paint);
Log.d("View", "line drawn");
}
}
}
At first I assumed onDraw() must not ever have been called, but I added the log messages and it was in fact being called and each line in the chart was being drawn. I also have overridden onMeausure() so I don't think thats the problem.
Just to test if anything would be drawn at all I added in a test TextView which appeared just fine. I Then found that my chartView instance in the Main activity was null because I didn't call the parent constructor properly. I fixed that though and still nothing was drawn. However, when I fixed the problem with the parent constructor, the TextView also disappeared.
This is my Main Activity:
public class MainActivity extends AppCompatActivity {
private ChartView chartView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent mainIntent = getIntent();
boolean testPassed = mainIntent.getBooleanExtra("test", false);
if (testPassed) {
Log.d("Main", "intents test passed");
}
chartView = (ChartView) findViewById(R.id.chartView);
}
and this is my layout XML file:
<?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"
android:visibility="visible"
tools:context=".MainActivity">
<Views.ChartView
android:id="#+id/chartView"
android:layout_width="425dp"
android:layout_height="634dp"
android:layout_marginEnd="601dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/textView"
android:layout_width="260dp"
android:layout_height="292dp"
android:layout_marginTop="256dp"
android:text="TextView"
android:textSize="100dp"
app:layout_constraintBottom_toTopOf="#+id/chartView"
app:layout_constraintEnd_toStartOf="#+id/chartView"
app:layout_constraintHorizontal_bias="0.582"
app:layout_constraintStart_toEndOf="#+id/chartView"
app:layout_constraintTop_toBottomOf="#+id/chartView"
app:layout_constraintVertical_bias="0.801" />
</androidx.constraintlayout.widget.ConstraintLayout>
Any help would be appreciated.

Updating X & Y coordinates when clicking a button

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

Custom EditText settext does not set the text

I am using a custom edittext but the problem is that I am unable to set a text for my custom edittext. Here is what all I tried from the available answers on SO,
setText not working for a Custom Edittext
This did not work still. I did not get any error,so no clued why it did not work.
Custom TextView - setText() called before constructor
This also did not work.
XML FILE
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#FFFFFF"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin" >
<com.random.practiceproject.LinedEditText
android:layout_width="301dp"
android:inputType="text"
android:layout_height="match_parent" />
</LinearLayout>
MainActivity
LinedEditText lt;
EditText et; //Normal edittext works
String s = "This is a sample string";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lt = new LinedEditText(this);
et = (EditText) findViewById(R.id.newt);
lt.setCursorVisible(true);
lt.setTextColor(Color.BLACK);
lt.setText(s,TextView.BufferType.EDITABLE);
et.setText(s, TextView.BufferType.EDITABLE);
}
Here is the code,
public class LinedEditText extends EditText {
private static Paint linePaint;
static {
linePaint = new Paint();
linePaint.setColor(Color.BLACK);
linePaint.setStyle(Paint.Style.STROKE);
}
public LinedEditText(Context context)
{
super(context);
}
public LinedEditText(Context context, AttributeSet attributes) {
super(context, attributes);
}
#Override
protected void onDraw(Canvas canvas) {
Rect bounds = new Rect();
int firstLineY = getLineBounds(0, bounds);
/*int firstLineY=0;
for(int i =0;i<getLineCount();i++)
{
firstLineY = (i + 1) * getLineHeight();
}*/
int lineHeight = getLineHeight();
int totalLines = Math.max(getLineCount(), getHeight() / lineHeight);
for (int i = 0; i < totalLines; i++) {
int lineY = firstLineY + i * lineHeight;
canvas.drawLine(bounds.left, lineY, bounds.right, lineY, linePaint);
}
super.onDraw(canvas);
}
}
The problem is that you create new instance of LineEditText in onCreate and working with it, but not adding to layout. In the layout there is another instance of LineEditText, that you don't use.
So you must either replace:
lt = new LinedEditText(this);
with:
lt = (LinedEditText) findViewById(/*provide your id*/)
or you need to add lt to layout through ViewGroup.addView(), but I think you need to use first variant.

Custom EditText does not show lines above

I am building a custom EditText from this answer, this is the output I am getting,
Problem
The lines are not starting right at the top,they are starting somewhere in the middle, what could be wrong.
Here is the code,
public class LinedEditText extends EditText {
private static Paint linePaint;
static {
linePaint = new Paint();
linePaint.setColor(Color.BLACK);
linePaint.setStyle(Paint.Style.STROKE);
}
public LinedEditText(Context context, AttributeSet attributes) {
super(context, attributes);
}
#Override
protected void onDraw(Canvas canvas) {
Rect bounds = new Rect();
int firstLineY = getLineBounds(0, bounds);
int lineHeight = getLineHeight();
int totalLines = Math.max(getLineCount(), getHeight() / lineHeight);
for (int i = 0; i < totalLines; i++) {
int lineY = firstLineY + i * lineHeight;
canvas.drawLine(bounds.left, lineY, bounds.right, lineY, linePaint);
}
super.onDraw(canvas);
}
}
Here is my XML,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/PeachPuff"
>
<TextView
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView"
android:padding="8dp"
android:layout_margin="10dp"
android:background="#drawable/shape"
android:layout_gravity="center_horizontal" />
<com.random.simplenotes.LinedEditText
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
All I did was added the gravity and everything was fine,
<com.random.simplenotes.LinedEditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textMultiLine"
android:gravity="top|left"
/>

Not able to add custom view into the layout programmatically

Hi I am creating a custom view in android.I have a LinerarLayout to which I am adding the custom views.I manage to add one custom view programmatically but if I add another it's not getting added into the layout.I don't know where am going wrong.My Main activity.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout container = (LinearLayout) findViewById(R.id.container);
final MyAnimationView animView = new MyAnimationView(this);
container.addView(animView);
final MyAnimationView animView1 = new MyAnimationView(this);
container.addView(animView1);
}
and my custom view class
public class MyAnimationView extends TextView implements ValueAnimator.AnimatorUpdateListener {
public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
AnimatorSet animation = null;
private float mDensity;
public MyAnimationView(Context context) {
super(context);
mDensity = getContext().getResources().getDisplayMetrics().density;
ShapeHolder ball0 = addBall(75f, 400f);
}
public MyAnimationView(Context context,float x,float y) {
super(context);
mDensity = getContext().getResources().getDisplayMetrics().density;
ShapeHolder ball0 = addBall(105f, 400f);
}
private void createAnimation() {
if (animation == null) {
ObjectAnimator anim0=ObjectAnimator.ofFloat(balls.get(0),"y",getHeight(),500f).setDuration(500);
animation = new AnimatorSet();
animation.playTogether(anim0);
anim0.addUpdateListener(this);
}
}
private ShapeHolder addBall(float x, float y) {
OvalShape circle = new OvalShape();
circle.resize(100f * mDensity, 100f * mDensity);
ShapeDrawable drawable = new ShapeDrawable(circle);
ShapeHolder shapeHolder = new ShapeHolder(drawable);
shapeHolder.setX(x - 25f);
shapeHolder.setY(y - 25f);
int red = (int)(100 + Math.random() * 155);
int green = (int)(100 + Math.random() * 155);
int blue = (int)(100 + Math.random() * 155);
int color = 0xff000000 | red << 16 | green << 8 | blue;
Paint paint = drawable.getPaint(); //new Paint(Paint.ANTI_ALIAS_FLAG);
int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
RadialGradient gradient = new RadialGradient(37.5f, 12.5f,
50f, color, darkColor, Shader.TileMode.CLAMP);
paint.setShader(gradient);
shapeHolder.setPaint(paint);
balls.add(shapeHolder);
return shapeHolder;
}
#Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < balls.size(); ++i) {
ShapeHolder shapeHolder = balls.get(i);
canvas.save();
canvas.translate(shapeHolder.getX(), shapeHolder.getY());
shapeHolder.getShape().draw(canvas);
canvas.restore();
}
}
public void startAnimation() {
createAnimation();
animation.start();
}
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
}
}
EDIT:here is my linear layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:id="#+id/startButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
any help will be greatly appreciated.
Just an assumption, donĀ“t know if it works. Try to do this in Your main:
LinearLayout container = (LinearLayout) findViewById(R.id.container);
final MyAnimationView animView = new MyAnimationView(this);
animView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.
WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f));
container.addView(animView);
final MyAnimationView animView1 = new MyAnimationView(this);
animView1.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.
WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f));
container.addView(animView1);
does it work?
No it will be added but you can't see it. because your first view will take the full space of your screen. And your second will be added in below of your first view so it will be hidden from visible part of your device. I also met the same problem. I solved this with two layouts. see here for my solution.
I assume this is the problem that is why I provided this solution if not kindly let me know..

Categories

Resources