If I have created a button in xml and i want to use this button multiple times but give them unique id's, how do i do that? I don't know how many buttons i will have, so i can't create a number of buttons in my xml-file. I want to be able to change the buttons id while running the program. I've tried to do button.setId() but then everything breaks and wont work.
You can make an independent button.xml file (or even do it as a style), then inflate that in your code as needed.
For instance, let's say you have an array of strings representing a list of countries, and you want a button for each country. This is nice because if you add or remove any, you only have to modify the array, not your xml or the for loop.
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
String[] countries = {"US", "Canada", "UK", "Australia"};
String country;
// Don't forget to add the following layout to your xml.
LinearLayout buttonLayout = (LinearLayout) findViewById(R.id.buttonLayout);
buttonLayout.removeAllViews();
for (int i = 0; i < countries.length(); i++) {
country = countries.getString(i);
Button temp = (Button)inflater.inflate(R.layout.button);
// Don't forget that id is an int, not a string.
button.setId(id);
button.setText(country);
buttonLayout.addView(temp);
}
Bonus: you can also include this button in another xml file, and update the id in the include statement as follows:
<include layout="#layout/button"
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1"
/>
The question is not very clear, but I think you can use dynamic button creation.
Button button = new Button();
// init it here
layout.add(button, new LayoutParams(...));
give id in xml like
<Button android:id="#+id/close"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="#string/title_close" />
When you are not sure of the instances you need in your application of a certain widget, then go for dynamic creation.
XML is mostly for static creation.
Related
I am attempting to add multiple EditTexts to a GridLayout and want to be able to specify which EditText is focused when the user clicks the "Next" button on the keyboard.
I thought this was going to be as simple as setting the setNextFocusDownId(...) method on the each EditText but unfortunately this doesn't seem to work.
My Layout file simply consists of a GridLayout with an EditText at the bottom:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:id="#+id/Grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
grid:columnCount="2">
</android.support.v7.widget.GridLayout>
<EditText
android:id="#+id/Last"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Last"/>
</LinearLayout>
And the code in my MainActivity.java file dynamically adds 10 EditTexts and attempts to assign the 'NextFocus' appropriately:
public class MainActivity extends AppCompatActivity
{
final Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridLayout grid = (GridLayout) findViewById(R.id.Grid);
int N=10;
grid.setRowCount((N+1)/2);
EditText prev = null;
for (int i=0 ; i<N ; i++)
{
EditText t = new EditText(context);
t.setInputType(InputType.TYPE_CLASS_TEXT);
t.setMaxLines(1);
t.setHint("" + i);
grid.addView(t);
if (prev != null)
prev.setNextFocusDownId(t.getId());
prev = t;
}
}
}
This does indeed create a grid with two columns of 5 elements however, clicking in the top cell and clicking Next arrow (">") on the keyboard takes you down a row rather then to the expected "NextFocused" ExitText.
Starting in the '0th' cell the "next" button takes you successively through the 'default' sequence:
'0' > '2' > '4' > '6' > '8' > "Last" (rather than the expected '0' > '1' > '2' > ... > '9' > "last").
Interestingly though, setting the NextFocused to findViewById(R.id.Last).getId() (instead of t.getId()) does cause focus to jump to "Last" from every cell in the grid. Any idea why this isn't working for t.getId().
The answer to this question seems to suggest simply setting 'setNextFocusDownId(...)' should do the trick however it's not working for me. Is there something different about accessing ID's of dynamically created View's that is different from XML defined Views that I don't quite understand?
Thanks,
Slarti.
Huh-harr, worked it out!
I didn't realise it but when a view is created dynamically it's ID is always created with a value if '-1'. One can however assign an ID to a view using the View's setId(int). From API level 17 onward one can generate an ID to use for this purpose using generateViewId() but prior to API 17 you have to come up with your own ID. Fortunately, according to this post, R.id... values are all greater than 0x00FFFFFF, so simply creating dynamic ID's by counting up from '0' should keep you well clear of the previously defined values.
Therefor, adding the line t.setId(i); as soon as the TextView is created in the example above resolves the problem nicely.
For another well answered question regarding dynamically assigned ID check out this question.
Cheers,
Slarti.
Is it possible to set textsize for multiple textview with same ID ? I have them with android:id :"#+id/lbl" ? Actually I set dp based on folder values/dimen.xml
TextView lbl=(TextView) findViewById(R.id.lbl);
lbl.setTextSize(dp);
The first textview only get this effect, but the rest of textview dont get this effect. Let me know how to solve this problem.
You need to do it separately as every activty/fragment/adapter has its own layouts (xml). In R.java they would have its own unique number.
android:textSize="24sp"
Everytime you add the views in XML, just add the text size
In android platform each view must have a unique id identified by "android:id" attribute of view. Although you are able to define multiple views with same id but android very first declaration and leaves the rest view as having no id.
Lets have an example now:
<TextView
android:id="#+id/response_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="27dp"
android:layout_toLeftOf="#+id/scan_format"
android:text="TextView" />
<TextView
android:id="#+id/response_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/response_text"
android:layout_marginBottom="74dp"
android:layout_toLeftOf="#+id/response_text"
android:text="Trepeattet" />
here are two textviews with same id, and now see R.java
public static final int radio=0x7f05002f;
public static final int response_text=0x7f050040;
public static final int scan_button=0x7f05003c;
public static final int scan_content=0x7f05003e;
public static final int scan_format=0x7f05003d;
in R.java only one textview is declared with its id(this hex id is created by platform compiler itself when you first run your code).
So although application does not produce any error in compile time or run time but will not do anything to any other view with same id either except very first one because of only one reference available that belongs to first textview.
As per this post here is what you can do:
View IDs are plain integers, so you can simply have an array of ids you want to change. For example:
int[] ids = { R.id.lbl1, R.id.lbl2, ... };
for (int id: ids) {
TextView lbl=(TextView) findViewById(id);
lbl.setTextSize(dp);
}
This will work.
You can get all TextViews of your parent view. Then check their ids in a loop
I've got three tabs, all from a layout xml file,say list.xml. In list.xml I've defined a EditText, something like this:
<EditText
android:id="#+id/filterText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/filterClear"
android:hint="#string/filterHint"
android:text="#string/filter">
</EditText>
However, it seems that if doing a orientation change and having typed something into one of the three EditTexts (all I guess with the same ID), the text doesn't restore to the same state. Sometimes (depending on which tab I've typed into) all fields are empty or all fields are filled.
What is the proper way to handle this?
I ended up having three separate layout files list1.xml, list2.xml, list3.xml, that only differed in the IDs. So list1.xml would have #+id/filterText1, list2.xml would have #+id/filterText2 and so on.
And then in the ListActivity.java file I used to have this as part of my onCreate:
setContentView(R.layout.list);
And several references to this throughout the activity:
EditText filter = (EditText)findViewById(R.id.filterText);
...
Instead I have now got this in my onCreate:
if(START_TAB1.equals(startMode)) { // Checks which tab is being started
setContentView(R.layout.list1); // Use appropriate layout
filterTextId = R.id.filterText1; // Save correct ID in a class variable
}
// And then the same "else if..." for all other tabs
And this when referencing the field itself throughout the activity:
EditText filter = (EditText)findViewById(filterTextId); // Use common ID
I'm having issues with understanding how I should organize my user interface in Android. My original plan was to create TextViews and ListViews programatically and change them when buttons are clicked, etc.
Here's my first simple attempt. viewFriends is a method within my Activity class. It's called when a menu button is pressed.
private void viewFriends()
{
mText = new TextView(this);
mText.setText("Gathering information...");
setContentView(mText);
...irrelevant code follows
Why doesn't this seemingly simple example work? How should I logically organize and manage my user interface objects (TextViews, ListViews, Buttons, etc).
Thanks.
The best work would be having those listviews and textviews in your XML files and give them a suitable ID like following:
<ListView
android:id="#+id/myList"
android:layout_width="wrap_content"
android:layout_weight="1"
/>
Just like above have your text view too in XML file an add the android:id attribute.
Once you define this way in your java file have references to them:
ListView myListObj = (ListView)findViewById(R.id.myList);
Now you have an object called myListObj in your java file and now you can do whatever you want to do with it.
:)
Let me if you find any issue in this so that I can update the answer to meet your specific need.
Don`t use setContentView in your method. Usually it should only be called once in the onCreate method of your activity.
Best predefine your bottons/TextViews in xml, get a handle for them (findViewbyId...)
and modify them that way.
If you create them programaticly, just add them to a view containter from your xml.
Like :
setContentView(R.layout.main);
Lets say in main.xml there is a LinearLayout with the id: root.
// get accces to that layout:
LinearLayout rootLayout = (LinearLayout) findViewById (R.id.root);
// create a new TextView
TextView tv1 = new TextView (this);
tv.setText("Hello!");
// add it to your base layout
rootLayout.addView(tv1);
// done! :)
Make a double check on what you are getting in "this".
change it to your java file name.this
You have to reload/refresh your activity once you change it.
Try this
#Override
protected void onResume() {
if(param.equalsIgnoreCase("gr"))
{
finish();
Intent myIntent = new Intent(yourActivity.this, yourActivity.class);
startActivity(myIntent);
}
Suppose I have a simple layout xml like the following:
button.xml:
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Are there any differences in the following calls? and which one should i use?
button = (Button) getLayoutInflater().inflate(R.layout.button, null);
and
View v = getLayoutInflater().inflate(R.layout.button, null);
button = (Button) v.findViewById(R.id.button01);
This one creates a new view with the given layout where 'R.layout.button' is generated by the name of the xml file 'button.xml'. Each time you call .inflate(...) you will get a new instance.
View v = getLayoutInflater().inflate(R.layout.button, null);
--
While that one finds an existing view within a layout where R.id.button01 is generated by the id name 'android:id="#+id/button01"'. Every time you call .findViewById(R.id.button01) you will get the same instance since the view 'v' will be the same.
button = (Button) v.findViewById(R.id.button01);
The first option is cleaner and slightly more efficient.
Your layout inflater will return a Button. With the first option, you gain access to the Button directly. With the second option, you cast the button down to a View and then look for the view with a given ID, which is an extra useless comparison, since the view with the ID you're looking for in the hierarchy happens to be the button itself. So in the second option, v == button.