Android: How to put custom elements on a circle/target - android

I need to create a sort of target and add objects to it, that have different colors and do different things when I click directly on them.
Any suggestion on how to achieve this? Maybe there is a library which I can use?

The formal solution is
Create roundedshape.xml inside drawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadiusRatio="4"
android:shape="ring"
android:thicknessRatio="5"
android:useLevel="false">
<solid android:color="#af08d7" />
<size
android:width="25dip"
android:height="25dip"></size>
</shape>
</item>
</layer-list>
Add RelativeLayout having android:background="#drawable/roundedshape"
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="300dp"
android:padding="50dp"
android:background="#drawable/roundedshape"
android:id="#+id/myRelativeLayout"
>
</RelativeLayout>
In your Activity add these codes to dynamically generate ImageButtons and add in Layout.
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.myRelativeLayout);
for (int j = 0; j < 4; j++) {
ImageButton myImageButton = new ImageButton(this); //generate ImageButton
myImageButton.setId(j); //Set Id of button
//Generate Random Number to place ImageButtons in random position
int min = 40;
int max = 60;
Random r = new Random();
int randomNum = r.nextInt(max - min + 1) + min;
myImageButton.setBackgroundResource(R.drawable.chatbox); //Set background of ImageButton
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
params.leftMargin = randomNum+j*randomNum; //Generate left margin dynamically
params.topMargin = randomNum +j*randomNum; //Generate right margin dynamically
relativeLayout.addView(myImageButton, params); //Add view
myImageButton.setOnClickListener(getButtonAndDoAction(myImageButton)); //Add OnClickListener
}
Add this method in Activity to handle the click event of your Image Buttons.
View.OnClickListener getButtonAndDoAction(final ImageButton button) {
return new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(MainActivity.this, "button clicked" +button.getId(), Toast.LENGTH_SHORT).show();
}
};
RESULT :
NOTE: I have added comments to make codes clear as possible

You could draw your image as:
Separate views - like in provided answer using RelativeLayout
Draw on canvas
Use opengl/existing graphics libraries.
It depends on your goals, maybe you need custom layout, maybe some sprites in your game or maybe bitmap to save into the file system.

Related

Buttons not displaying from FOR loop

I have been attempting to programmatically add buttons based on a list of values.
PROBLEM: Only one button is produced, rather than a series. This button contains the information of the last value in the array.
I gather an array of values aptly named 'values', I then use a for loop to add the buttons.
Here is the code of my loop to add buttons:
public void updateButtons(List<String> values, View rootView) {
//Find relative layout
RelativeLayout rl = (RelativeLayout) rootView.findViewById(R.id.RelativeLayoutManage);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(50, 10, 50, 10);
for (String mTrip : values) {
//New button
Button Postbtn = new Button(mContext);
//Style
Postbtn.setBackgroundResource(R.drawable.buttonshape);
Postbtn.setTextColor(getResources().getColor(R.color.DarkGreen));
Postbtn.setTextSize(25);
//set text
Postbtn.setText(mTrip.toString());
//set id
Postbtn.setId(i);
int id_ = Postbtn.getId();
//Add to view
rl.addView(Postbtn, params);
Postbtn = ((Button) rootView.findViewById(id_));
//Add listener
Postbtn.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
Log.v("TripNumber", Integer.toString(i));
//TODO: Change Fragment
}
});
i++;
}
}
And my corresponding layout file if needed:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/RelativeLayoutManage"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
</RelativeLayout>
Seems that they might be overlapping each other. You need to use a LinearLayout
<LinearLayout android:id="#+id/RelativeLayoutManage"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
/>
You are adding Button to RelativeLayout. In your current code all your buttons are present but one above other. You should make one below/above other to make all buttons visible. Else use a LinearLayout
I solved the problem by positioning each button as it is added to the layout. Simply using:
params.addRule(RelativeLayout.BELOW, Postbtn.getId() - 1);
Postbtn.setLayoutParams(params);

Setting views dynamically with LayoutParams.addRule setting to the last position of the view

I'm dynamically adding views to a relative layout and programatically defining them. The views can be moved around the screen so their position is changing.
When I try to set a view (button2) to sit below another view (button1), button2 gets placed in the old location of button1 (the default location of where views get added before moved). I've linked images to hopefully convey this better.
This is the Original Layout
Layout after Button2 is re-positioned
I have a background LinkedList keeping track of all view changes and view attributes for the layout if that makes a difference.
Here are the code functions:
How i'm re-positioning Button1:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(positioningLayout);
baseLayout.addView(b);
Repositioning views below another view Code fragment:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.invalidate();
How I'm adding the views to the layout.
uiList.addView(new Buttons(this), "BUTTON");
setDialogView(uiList.getLast());
showDialog(SET_ID);
reloadUI();
setDialogView is just passing the view to the Dialog SET_ID so that I can manually assign an ID to the view (for testing).
reloadUI() just finds the last view added to the background LinkedList and adds it to the relativeLayout using .addView;
If you require more code please let me know. Am I missing a call to update the view layouts after making a change to the relativeLayout child views? It seems like the view is getting re-positioned visually but the actual LayoutParams are not updating so when you set Button2 to Button1 it's getting the old position.
Is there a way to force a relative layout view re-position?
I think you should try simple solution - replace b.invalidate() with b.requestLayout(). For more background check this link. I didn't test it but I hope it will work. So the code should look like:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.requestLayout();
Or maybe you can simplify this to:
Buttons b = (Buttons) viewIndex;
((RelativeLayout.LayoutParams) b.getLayoutParams()).addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.requestLayout();
You seem to be in the right track but is doing a small mistake. Without more code it is quite difficult to provide the actual solution. But I will try to point out the mistake.
See, to relatively position items programmatically in a RelativeLayout you must assign unique ids to each of them.
Like,
Button b = new Button(this);
b.setId(1);
Button c = new Button(this);
c.setId(2);
Each element should have unique ids.
Now if you want to place the Button b vertically in the center,
layout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(layout);
Now if you want to place Button c below it,
layout.addRule(RelativeLayout.BELOW, b.getId());
layout.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
b.setLayoutparams(layout);
This will certainly place the button c below button b. As you said you can use a any data structure of your choice to keep track of the ids of each elements.
This is only a detail example on how you move the button correctly. So first, create a unique id for the View, i.e. create a new XML resource file in res/values/, and name it ids.xml:
And the content of ids.xml is:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="button_1" type="id"/>
<item name="button_2" type="id"/>
</resources>
We have to set an id to your main layout:
<?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:id="#+id/layout_main"> <!-- the id -->
<!-- content of this layout -->
</RelativeLayout>
Then, let's create the Buttons:
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout_main);
final Button button1 = new Button(this);
button1.setId(R.id.button_1);
button1.setText("BUTTON 1");
button1.setTextColor(Color.BLACK);
final Button button2 = new Button(this);
button2.setId(R.id.button_2);
button2.setText("BUTTON 2");
button2.setTextColor(Color.BLACK);
relativeLayout.addView(button1, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
relativeLayout.addView(button2, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) button1.getLayoutParams();
params1.addRule(RelativeLayout.CENTER_IN_PARENT); // set to the center of screen
button1.setLayoutParams(params1);
final RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) button2.getLayoutParams();
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
button2.setLayoutParams(params2);
button2.setOnClickListener(new View.OnClickListener() {
#SuppressLint("NewApi")
#Override
public void onClick(View v) {
/* We need to remove the existing rules and update it!
* For API 16 and earlier, set the rule to 0, e.g. --> layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
* For API 17 and higher, call layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
*/
int api = android.os.Build.VERSION.SDK_INT;
if (api >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // API level 17
params2.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
}else if (api < Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
}
params2.addRule(RelativeLayout.CENTER_IN_PARENT);
params2.addRule(RelativeLayout.BELOW, R.id.button_1); // place below button1
button2.setLayoutParams(params2);
}
});
So once you click on button2, it will move to below button1.

android: setImageResource on Imagebuttons inflated to a view

I would like to inflate imagebuttons programmatically to a linearlayoutm, coded as follows:
Code:
public void set_keyboard_words(int row, int start, int end)
{
for (int p = start; p <= end; p++)
{
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(btn_ball_sq,btn_ball_sq);
params.setMargins(0, 0, 0, 0);
keyboard_btn = new ImageButton(this);
keyboard_btn.setId(p);
final int id_ = keyboard_btn.getId();
keyboard_btn.setImageResource(BUTTON_IMG[p-1]);
keyboard_btn.setBackgroundResource(R.drawable.btn_blue_selector);
keyboard_btn.setScaleType(ImageView.ScaleType.FIT_XY);
keyRow1.addView(keyboard_btn, params);
keyboard_btn.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
button_action(id_);
}
});
}
}
Xml:
<LinearLayout
android:id="#+id/keyRow1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:splitMotionEvents="false" >
</LinearLayout>
Background:
The imagebuttons are some balls.
The imagebuttons could be inflated to the linearlayout keyRow1.
However, I do not know how to set the image resources to the imagebuttons correctly. The balls inflated are so small instead of fitting to XY of the buttons.
Screenshot as follows:
If image set as keyboard_btn.setImageResource(BUTTON_IMG[p-1]); (with blue backgrounds as BackgroundResource for seeing the actual size of button), the balls are very small
If image set as keyboard_btn.setBackgroundResource(BUTTON_IMG[p-1]);, the size is now proper but the actual backgroundResource cannot be set anymore
Question:
I would like to use the method of setImageResource for the imagebuttons as the button background would later be changed to other background image upon pressed.
How could I set the imagebutton's image using setImageResource but with size of balls similar to the 2nd screenshot??
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
keyboard_btn = new ImageButton(this);
keyboard_btn.setId(p);
final int id_ = keyboard_btn.getId();
keyboard_btn.setImageResource(BUTTON_IMG[p-1]);
keyboard_btn.setBackgroundResource(R.drawable.btn_blue_selector);
keyboard_btn.setLayoutParams(params);
Just try the above code, if the image doesn't shrink then you need to optimize the image based on the width you get for each button from screen width.

Change checkbox size android without using XML

Thanks in advance for the help.
I have a checkbox that I am creating in a method call
public int myMethod(Context context, doThing) {
if(doThing){
this.checkBox = new CheckBox(context);
do some stuff...
return 1;
}else{
do something else...
return 0;
}
}
I would like to change the size of the checkbox (the actual box not the box and text combo) with a call like checkBox.setBoxSize(mySize). setBoxSize is not a native android method. Is it possible to do this, and if it is, how might I go about it?
If you want to create your checkBox with predefined width and height you can use this method:
this.checkBox = new CheckBox(context);
this.checkBox.setLayoutParams(new LinearLayout.LayoutParams(width, height)); // or if your parent is RelativeLayout use RelativeLayout.LayoutParams(width, height)
Note, that your width and height are in pixels.
If you want to change already existing layout params, you should do something like this:
private void setBoxSize(CheckBox checkBox) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) checkBox.getLayoutParams(); // or RelativeLayout.LayoutParams
params.height = yourHeightInPixels;
params.width = yourWidthInPixels;
checkBox.setLayoutParams(params);
}
EDIT:
In that case, if you want to change size of the checkbox's button, you could only use one of this methods
checkBox.setButtonDrawable(int resId);
checkBox.setButtonDrawable(Drawable d);
and set the right size of your drawables. Unfortunately, Android doesn't have methods to manipulate button (as you mentioned - "box") of the checkbox.
Example of the drawable, that is using as checkbox's button:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true"
android:drawable="#drawable/ic_check_on" /> <!-- checked -->
<item android:state_checked="false"
android:drawable="#drawable/ic_check_off" />
</selector>
You should set the layout Params for the checkbox like this
//width and height are in pixels
checkbox.setLayoutParams(new ViewGroup.LayoutParams(width,height));

on draw on an android button

First I'm new to android.
Okay, here goes.
I'm attempting to override the onDraw of a button, because I want to create a different styled button.. Something ever so slightly different.
Now I can draw the background quite easily, but I can't for the life of me figure out why I have no text on my button.
public class TriButton extends Button {
private Paint m_paint = new Paint();
private int m_color = 0XFF92C84D; //LIKE AN OLIVE GREEN..
public TriButton(Context context) {
super(context);
setBackgroundColor(Color.BLACK);
}
public void onDraw(Canvas iCanvas) {
//draw the button background
m_paint.setColor(m_color);
iCanvas.drawRoundRect(new RectF(0, 0,getWidth(),getHeight()), 30, 30, m_paint);
//draw the text
m_paint.setColor(Color.WHITE);
iCanvas.drawText( "bash is king", 0, 0, m_paint);
}
public static RelativeLayout.LayoutParams GetRelativeParam(int iLeft, int iTop, int iWidth, int iHeight){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(iHeight, iWidth);
params.leftMargin = iLeft;
params.topMargin = iTop;
return params;
}
}
Here's the code that creates the button.
RelativeLayout relLay = new RelativeLayout(this);
m_button = new TriButton(this);
setContentView(relLay);
relLay.addView(m_button, m_button.GetRelativeParam(0,0,100,500) );
Now everything I've read has me expecting to see text in my olive green button oval button.
The olive green oval shows up, but it doesn't have text in it.. It is a void. A green smudge that laughs at me and reminds me with it's silence, that I am utterly alone :(.
Normally you would do that via xml.
for examle put the following in the layout of your custom class:
android:background="#drawable/shape"
and then something like that which would be shape.xml placed in /drawable.
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="2px"
android:color="#555555"/>
<corners
android:radius="10px"/>
<gradient
android:startColor="#000000"
android:endColor="#ffffff"
android:angle="90"/>
</shape>
This example creates a rounded rectangle with a border and a gradient in it. Let me know if you need further explanation.
See http://developer.android.com/guide/topics/ui/themes.html
Ok, I figured, it's not visible because coordinates are (0,0) which is bottom left of the button, so text is not visible. Try this and it works:
iCanvas.drawText( "bash is king", 0, 15, m_paint);
Olive green is a good choice btw :)
To draw text in your button, get rid of the call to drawText() within the onDraw of your button class. All you need to do is call setText on the instance of the button since Button extends view:
m_button.setText("bash is king");
Also, to make a custom button, you may want to consider just using an Image and assigning an OnClickListener to it.

Categories

Resources