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));
Related
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.
I have a method that creates several buttons
public Button[] generaBottoniRisposta(int numeroBottoni, Context context){
Button bottoni[]= new Button[numeroBottoni];
/*genero un tot di bottoni in base a numeroBottoni, รจ necessario avere il context*/
for(int i=0; i < bottoni.length;i++){
bottoni[i] = new Button(context);
bottoni[i].setId(i);
bottoni[i].setText(String.valueOf(i+1));
LayoutParams param = new LinearLayout.LayoutParams(50, 50);
bottoni[i].setLayoutParams(param);
}
return bottoni;
}
and then another method that add them to a gridlayout.
I want to set the width of those buttons, but i'm not able to do it.
I tried a lot of stuff, setWidth(), setMaxWidth(), invalidate() etc.
Something weird happens. If I try to make the button bigger than its default size it works, if i try to make the button smaller than its default size it doesn't work!
How should I do? thank you
Try using LayoutParams, something like..
RelativeLayout.LayoutParams rel_bottone = new RelativeLayout.LayoutParams(buttonWidth, buttonHeight);
button.setLayoutParams(rel_bottone);
And the layout depends on the parent layout that contains the buttons..
I think setlayoutparams should do what you want. Like in the answer in this thread.
Set View Width Programmatically
try this:
LinearLayout.LayoutParams params = button.getLayoutParams();
params.width = 100;
button.setLayoutParams(params);
one more thing LinearLayout.LayoutParams is used when parent is a LinearLayout and when parent is RelativeLayout use RelativeLayout.LayoutParams.
Try something like this :
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, height);
button.setLayoutParams(params);
My buttons are inside a gridlayout. I tried to use GridLayout.LayoutParams giving the width of the cells, instead of trying to set the width of the button, and now it seems to work.
this is the code I use to add the buttons to the GridLayout
Spec row = GridLayout.spec(numeroRiga, 1);
Spec colspan = GridLayout.spec(numeroColonna, 1);
GridLayout.LayoutParams gridLayoutParam = new GridLayout.LayoutParams(row,colspan);
gridLayoutParam.width=50;
gridLayoutParam.height=50;
gridLayout.addView(button,gridLayoutParam);
But i'm wondering if i can set the width of the buttons in a similar way.
I know that I could do all of this easily with a custom toast layout, but in creating a custom layout, I would no longer be using the system's default toast view.
Example: Toasts of course look different in Android 2.2 vs Android 4.0. If I create a custom view for my toast, then it will look the exact same in both versions, but what I want is for it to retain its... "Androidiness" for lack of a better word. Basically, does anyone know of a default toast XML layout? Is that even possible?
This is the default layout used by Toasts.
transient_notification
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/toast_frame">
<TextView
android:id="#android:id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="#style/TextAppearance.Small"
android:textColor="#color/bright_foreground_dark"
android:shadowColor="#BB000000"
android:shadowRadius="2.75"/>
</LinearLayout>
These are the enter and exit animations
ENTER
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#interpolator/decelerate_quad"
android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="#android:integer/config_longAnimTime" />
EXIT
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#interpolator/accelerate_quad"
android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="#android:integer/config_longAnimTime" />
toast_frame_holo.9 is the name of the resource used for the background. Search the SDK to find all of the sizes.
And here is the full source for Toasts
If you're unsure about any of that, search the SDK for all of the resources, that's where I looked.
On my ICS device I recently had a message fail to send due to loss of connection. It looked like a toast but had a different font size, was two lines long, and had a red border. It basically said that the message failed to send (or connection error).
That might be similar to what you're looking for?
I wanted to retain the default toast too but found solution which showed me how to create a single toast layout for all system. So I created this helper. I know, it's a hack, but it works fine for me.
Here I added an image to the toast in front of the text without touching its native appearance. You could easily modify the text color and size here.
Maybe someone might be interested in this code snippet...
private static Toast makeImageToast(int imageResId, CharSequence text, int duration) {
Toast toast = Toast.makeText(mContext, text, duration);
View rootView = toast.getView();
LinearLayout linearLayout = null;
TextView messageTextView = null;
// check (expected) toast layout
if (rootView instanceof LinearLayout) {
linearLayout = (LinearLayout) rootView;
if (linearLayout.getChildCount() == 1) {
View child = linearLayout.getChildAt(0);
if (child instanceof TextView) {
messageTextView = (TextView) child;
}
}
}
// cancel modification because toast layout is not what we expected
if (linearLayout == null || messageTextView == null) {
// failed to create image toast layout, using usual toast
return toast;
}
ViewGroup.LayoutParams textParams = messageTextView.getLayoutParams();
((LinearLayout.LayoutParams) textParams).gravity = Gravity.CENTER_VERTICAL;
// convert dip dimension
int imageSize = dipToPixel(25);
int imageMargin = dipToPixel(15);
// setup image view layout parameters
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(imageSize, imageSize);
imageParams.setMargins(0, 0, imageMargin, 0);
imageParams.gravity = Gravity.CENTER_VERTICAL;
// setup image view
ImageView imageView = new ImageView(mContext);
imageView.setId(TOAST_IMAGE_ID);
imageView.setImageResource(imageResId);
imageView.setLayoutParams(imageParams);
// modify root layout
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.addView(imageView, 0);
return toast;
}
public static int dipToPixel(float dip) {
return (int) (dip * mContext.getResources().getDisplayMetrics().density + 0.5f);
}
I am writing an Android app. I have an activity in my main project which inherits from an activity in my library project. I have a custom titlebar in the base activity which has a button, which uses the following style:
<style name="TitleButton">
<item name="android:padding">6dp</item>
<item name="android:layout_width">48dip</item>
<item name="android:layout_height">48dip</item>
<item name="android:layout_gravity">right</item>
</style>
Works fine. In my child activity, I want to add a button. I can add the button, and it clicks and works fine, but it LOOKS wrong. I am adding the button as so:
ImageView imgAdd = new ImageView(this, null, R.style.TitleButton);
imgAdd.setImageResource(R.drawable.add);
imgAdd.setClickable(true);
imgAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
addGroup();
}
});
FrameLayout tb = (FrameLayout) this.findViewById(R.id.Header);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
tb.findViewById(R.id.TitleClose).getLayoutParams()
);
lp.gravity = Gravity.RIGHT;
lp.width = 48;
lp.height = 48;
lp.setMargins(0, 9, 68, 0);
imgAdd.setLayoutParams(lp);
tb.addView(imgAdd, 1);
Notice how the Add button which I've added through code is too big, and offset too much. I'm figuring it must be due to what was pointed out in the comments on this answer, that setting the width and height so sets them in pixels, where as the XML layout sets them in dip. So, my question is, when setting layout params in code, how can you set the unit, so that I may set my new add button to be measured in dip instead of in pixels so that it will display right?
You can use DisplayMetrics to get current density and use it to set width, height and margins accordingly (reference here: px = dp * (dpi / 160))
I want to add a view inside a FrameLayout programmatically and to place it in a specific point within the layout with a specific width and height. Does FrameLayout support this? If not, should I use an intermediate ViewGroup to achieve this?
int x; // Can be negative?
int y; // Can be negative?
int width;
int height;
View v = new View(context);
// v.setLayoutParams(?); // What do I put here?
frameLayout.addView(v);
My initial idea was to add an AbsoluteLayout to the FrameLayout and place the view inside the AbsoluteLayout. Unfortunately I just found out that AbsoluteLayout is deprecated.
Any pointers will be much appreciated. Thanks.
The following example (working code) shows how to place a view (EditText) inside of a FrameLayout. Also it shows how to set the position of the EditText using the setPadding setter of the FrameLayout (everytime the user clicks on the FrameLayout, the position of the EditText is set to the position of the click):
public class TextToolTestActivity extends Activity{
FrameLayout frmLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
frmLayout = (FrameLayout)findViewById(R.id.frameLayout1);
frmLayout.setFocusable(true);
EditText et = new EditText(this);
frmLayout.addView(et,100,100);
frmLayout.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("TESTING","touch x,y == " + event.getX() + "," + event.getY() );
frmLayout.setPadding(Math.round(event.getX()),Math.round(event.getY()) , 0, 0);
return true;
}
});
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="#+id/frameLayout1"
android:layout_height="fill_parent" android:layout_width="fill_parent">
</FrameLayout>
</LinearLayout>
You can also add a margin around the newly added view to position it inside the FrameLayout.
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.main); // or some other R.id.xxx
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(0, metrics.heightPixels - 20, 0, 0);
View v = new View(context);
v.setLayoutParams(params);
frameLayout.addView(v);
This will position the FrameLayout 20 pixels from the bottom of the screen.
Edit: completed the example so it stands by itself. And oh, yes it does work.
It's true that with FrameLayout all children are pegged to the top left of the screen, but you still have some control with setting their padding. If you set different padding values to different children, they will show up at different places in the FrameLayout.
From the link Quinn1000 provided:
You can add multiple children to a FrameLayout, but all children are pegged to the top left of the screen.
This means you can't put your View at a specific point inside the FrameLayout (except you want it to be at the top left corner :-)).
If you need the absolute positioning of the View, try the AbsoluteLayout:
A layout that lets you specify exact locations (x/y coordinates) of its children. Absolute layouts are less flexible and harder to maintain than other types of layouts without absolute positioning.
As for setting the width and height of the View, also like Quinn1000 said, you supply the v.setLayoutParams() method a LayoutParams object, depending on the container you chose (AbsoluteLayout, LinearLayout, etc.)
The thread here on stackOverflow at
How do you setLayoutParams() for an ImageView?
covers it somewhat.
For instance:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(30, 30);
yourImageView.setLayoutParams(layoutParams);
implies that you need to be defining a LinearLayout.LayoutParams (or in your case a FrameLayout.layoutParams) object to pass to the setLayoutParams method of your v object.
At
http://developer.android.com/reference/android/widget/FrameLayout.html
it almost makes it looks like you could ask your v to:
generateDefaultLayoutParams () via this method if you have not defined the parameters specifically.
But it's late, and those links are making my eyes bleed a little. Let me know if they nhelp any :-)