I have looked at other questions regarding this problem but the solutions don't work for me. I have a number of edittext fields on a page and want to be able to reset them with one button press. I implemented the solution from this thread but I have nested linear layouts and it only clears the edittext that is a direct child of the main container. How can I get it to find all of the edittext fields or will I have to reference each one?
My xml file structure is as follows:
<ScrollView>
<LinearLayout android:id="#+id/MainParent">
<LinearLayout>
TextView
EditText
</LinearLayout>
<LinearLayout>
TextView
EditText
</LinearLayout>
<LinearLayout>
TextView
EditText
</LinearLayout>
EditText
<LinearLayout>
Button1
Button2
</LinearLayout>
</LinearLayout>
</ScrollView>
Snippet from Java File:
ViewGroup group = (ViewGroup)findViewById(R.id.MainParent);
for (int i = 0, count = group.getChildCount(); i < count; ++i) {
View view = group.getChildAt(i);
if (view instanceof EditText) {
((EditText)view).setText("");
}
If you are not interested in referencing each EditText specifically, I'd make a recursive function to handle the hierarchy.
public void clearAll(ViewGroup root) {
for (int i = 0, j = root.getChildCount(); i < j, i++) {
View view = root.getChildAt(i);
if (view instanceof ViewGroup) {
clearAll((ViewGroup) view);
continue;
}
if (view instanceof EditText) {
((EditText) view).setText("");
continue;
}
}
}
Then you just call:
clearAll((ViewGroup) findViewById(R.id.MainParent));
After onClick of any action do below step :
EditText firstEditText = (EditText) findViewById(R.id.yoursXmlId);
firstEditText.setText("");
LinearLayout group = (LinearLayout)findViewById(R.id.MainParent);
for (int i = 0, count = group.getChildCount(); i < count; ++i)
{
View view = group.getChildAt(i);
if (view instanceof EditText) {
((EditText)view).setText("");
}
Related
I have a LinearLayout ("ll") that is already created in xml and the app dynamically creates another LinearLayout inside of it and creates an EditText and a Button inside of that view. The button makes the whole LinearLayout destroy itself along with the EditText and Button inside it (the whole system is a player name entering activity). Anyway, I am trying to find a way to get the text from all of the EditTexts. I have tried using a for loop on "ll" and using ll.getChildAt() but I can't seem to use .getChildAt() on whatever ll.getChildAt() generates because getChildAt() generates a "View" not a "LinearLayout." I basically just need a way to search two children in, rather than just one. Also, if there is just a better way I should be doing this, let me know. I'm open to suggestions.
Here's my code if it will help:
NewGameCreate.java
public class NewGameCreate extends Activity {
int numOfPlayers = 0;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_game_create);
}
public void newPlayer(View view) {
numOfPlayers++;
final LinearLayout ll = findViewById(R.id.playerView);
final LinearLayout llNew = new LinearLayout(getApplicationContext());
llNew.setOrientation(LinearLayout.HORIZONTAL);
llNew.setId(numOfPlayers);
ll.addView(llNew);
EditText newName = new EditText(this);
newName.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1));
newName.setHint("Enter Player Name");
newName.setId(numOfPlayers);
newName.setWidth(0);
llNew.addView(newName);
final Button delete = new Button(this);
delete.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0));
delete.setText("Delete");
delete.setId(numOfPlayers);
delete.setWidth(0);
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int id = delete.getId();
ll.removeViewInLayout(findViewById(id));
Drawable back = ll.getBackground();
ll.setBackgroundColor(00000000);
ll.setBackground(back);
ll.invalidate();
}
});
llNew.addView(delete);
}
public void startGame(View view){
LinearLayout ll = findViewById(R.id.playerView);
List text = new ArrayList();
for(int loop = 0; loop < ll.getChildCount(); loop++) {
//this is the code in question and where I want to get the text from
//all my EditTexts
LinearLayout inner = ll.getChildAt(loop);
}
}
}
I think I found the answer to it. You need to change a little bit of code in the startGame() method I m providing the code for startGame below.
public void startGame(View view) {
LinearLayout ll = findViewById(R.id.playerView);
List text = new ArrayList();
for (int loop = 0; loop < ll.getChildCount(); loop++) {
//this is the code in question and where I want to get the text from
//all my EditTexts
LinearLayout inner = (LinearLayout) ll.getChildAt(loop);
for (int j = 0; j < inner.getChildCount(); j++) {
if (inner.getChildAt(j) instanceof EditText) {
EditText textET = (EditText) inner.getChildAt(j);
Log.d("TAG",textET.getText().toString());
}
}
}
}
In the above code you were able to get the first child only but as you have added a linearLayout with orientation Horizontal in a parent LinearLayout with orientation Vertical, you have written code for the child of parent layout i.e playerView. I have modified the code to get the elements of the child Linear layout and Log prints all the text from the EditText.
Hope that helps!!
This question already has answers here:
Uncheck all RadioButton in a RadioButtonGroup
(3 answers)
Closed 7 years ago.
I have a drawer menu with a dynamic option inside it and I got to fill it.
I want to clear all the child of a RadioGroup inside adapter but I didn't find anything.
p.s: I fill all RadioGroup with addView and fill it with CheckBox
ps2: The question is not about the check and uncheck. I want to find out how can remove all child of a view (like RadioGroup).
viewHolder.mRadioGroup.setVisibility(View.VISIBLE);
/////clear viewHolder.mRadioGroup child hear, befor add new child to it
for (int i; i<10; i++) {
RadioButton radioButton = new RadioButton(mContext);
radioButton.setText(selectableValue.getValue());
viewHolder.mRadioGroup.addView(radioButton);
}
Try This :
int count = radioGroup.getChildCount();
if(count>0) {
for (int i=count-1;i>=0;i--) {
View o = radioGroup.getChildAt(i);
if (o instanceof RadioButton) {
radioGroup.removeViewAt(i);
}
}
}
This taken from link here for complex nested layout
private static void disable(ViewGroup layout) {
layout.setEnabled(false);
for (int i = 0; i < layout.getChildCount(); i++) {
View child = layout.getChildAt(i);
if (child instanceof ViewGroup) {
disable((ViewGroup) child);
} else {
child.setEnabled(false);
}
}
}
I have 16 Buttons in my Activity and I have to initialize those inside onCreate().
Is there any way to initialize all buttons in one single line code?(loops etc.)
Code should take all buttons R.id. from XML Layout and process....
Let's say you named your button button_0, button_1, .. button_15. You can do:
for (int i = 0; i < 16; i++) {
int id = getResources().getIdentifier("button_"+i, "id", getPackageName());
button[i] = (Button) findViewById(id);
}
Well, if all 16 of those buttons are inside one view or layout, then you could do the following.
ArrayList<View> allButtons;
allButtons = ((LinearLayout) findViewById(R.id.button_container)).getTouchables();
This assumes that your container (in this example a LinearLayout) contains no Touchable that is not a Button.
use Butterknife view injections library
Download Android ButterKnife Zelezny plugin for Android Studio or Intellij IDEA
and initialize all your views from current layout by 1 click
For xamarin android :
List<Button>() allButtons = new List<Button>();
for (int i = 1; i < 15; i++)
{
int id = this.Resources.GetIdentifier("btn" + i.ToString(), "id", this.PackageName);
Button btn = (Button)FindViewById(id);
allButtons.Add(btn);
}
This method takes all buttons inside the layout, hope it helps. Easy to implement & you can use it for almost every project, no libraries required.
public List<Button> getAllButtons(ViewGroup layout){
List<Button> btn = new ArrayList<>();
for(int i =0; i< layout.getChildCount(); i++){
View v =layout.getChildAt(i);
if(v instanceof Button){
btn.add((Button) v);
}
}
return btn;
}
Example
List<Button> btn_list = getAllButtons(myRelativeLayout);
Button my_btn = btn_list.get(0);
my_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("btn_test", "onClick: hello");
}
});
If you are using Kotlin, and your buttons have ids in the form of button1, button2... button16, you can do something like this:
var btn = ArrayList<Button>(16)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game_screen)
for(i in 0 until 16) {
var id = resources.getIdentifier("button"+(i+1), "id", packageName)
btn.add(findViewById<View>(id) as Button)
btn[i].setText("something") //or do whatever now
}
}
If you only know the container id or the button ids are all different try this:
Activity(on create method before setContentView)
List<Integer> idButtons= new ArrayList<>();
//container_button is my button container
RelativeLayout containerButton = findViewById(R.id.container_button);
for(int i =0; i < containerButton.getChildCount(); i++){
View v = containerButton.getChildAt(i);
if(v instanceof Button){
idButtons.add(((Button) v).getId());
}
}
Layout
<RelativeLayout
android:id="#+id/container_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="1"
android:layout_marginEnd="0dp">
<Button
android:id="#+id/buttonac"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/red_button"
android:textColor="#android:color/white"
android:text="AC"
android:onClick="pulsacion" />
<Button
android:id="#+id/buttondel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/buttonac"
android:layout_alignBottom="#+id/buttonac"
android:background="#drawable/red_button"
android:textColor="#android:color/white"
android:text="DEL"
android:onClick="pulsacion" />
[...]
</RelativeLayout>
can anyone help me with coding a method to get all EditTexts in a view? I would like to implement the solution htafoya posted here:
How to hide soft keyboard on android after clicking outside EditText?
Unfortunately the getFields() method is missing and htafoya did not answer our request to share his getFields() method.
EDIT
MByD pointed me to an error, thus making my answer almost identical to that of blackbelt. I have edited mine to the correct approach.
You could do a for-each loop and then check if each view is of the type EditText:
ArrayList<EditText> myEditTextList = new ArrayList<EditText>();
for( int i = 0; i < myLayout.getChildCount(); i++ )
if( myLayout.getChildAt( i ) instanceof EditText )
myEditTextList.add( (EditText) myLayout.getChildAt( i ) );
You could also, instead of having a list of EditTexts, have a list of ID's and then just add the id of the child to the list: myIdList.add( child.getId() );
To access your layout you need to get a reference for it. This means you need to provide an ID for your layout in your XML:
<LinearLayout android:id="#+id/myLinearLayout" >
//Here is where your EditTexts would be declared
</LinearLayout>
Then when you inflate the layout in your activity you just make sure to save a reference to it:
LinearLayout myLinearLayout;
public void onCreate( Bundle savedInstanceState ) {
super( savedInstanceState );
setContentView( R.layout.myLayoutWithEditTexts );
...
myLinearLayout = (LinearLayout) findViewById( R.id.myLinearLayout );
}
You then have a reference to your the holder of your EditTexts within the activity.
Here's a method I wrote to recursively check all EditText children of a ViewGroup, handy for a long sign-up form I had to do and probably more maintainable.
private EditText traverseEditTexts(ViewGroup v)
{
EditText invalid = null;
for (int i = 0; i < v.getChildCount(); i++)
{
Object child = v.getChildAt(i);
if (child instanceof EditText)
{
EditText e = (EditText)child;
if(e.getText().length() == 0) // Whatever logic here to determine if valid.
{
return e; // Stops at first invalid one. But you could add this to a list.
}
}
else if(child instanceof ViewGroup)
{
invalid = traverseEditTexts((ViewGroup)child); // Recursive call.
if(invalid != null)
{
break;
}
}
}
return invalid;
}
private boolean validateFields()
{
EditText emptyText = traverseEditTexts(mainLayout);
if(emptyText != null)
{
Toast.makeText(this, "This field cannot be empty.", Toast.LENGTH_SHORT).show();
emptyText.requestFocus(); // Scrolls view to this field.
}
return emptyText == null;
}
You can do it by calling View#getFocusables, which will return an arraylist of all focusable views in a View.
Then you can either check if they are EditTexts, with (instanceof) or act on all of them.
This Methods walks recursively through all ViewGroups and collects their TextViews. I use this to assign a new Color to all TextViews (even those embedded in predefined Widgets like Switch etc that make use of TextViews)
private HashSet<TextView> getTextViews(ViewGroup root){
HashSet<TextView> views=new HashSet<>();
for(int i=0;i<root.getChildCount();i++){
View v=root.getChildAt(i);
if(v instanceof TextView){
views.add((TextView)v);
}else if(v instanceof ViewGroup){
views.addAll(getTextViews((ViewGroup)v));
}
}
return views;
}
Get all Edit Text in any type of layout.
public List<EditText> getAllEditTexts(ViewGroup layout){
List<EditText> views = new ArrayList<>();
for(int i =0; i< layout.getChildCount(); i++){
View v =layout.getChildAt(i);
if(v instanceof EditText){
views.add((EditText)v);
}
}
return views;
}
I have a view with radios, inputs and a button and when I click it, I want to check that all inputs contain information. How can I iterate through the view's elements in the activity and check if every textview meets the aforementioned requirement ? Thanks.
I've done something similar in some code I don't have with me at the moment, but from memory it should be something like this (assuming a parent view LinearLayout with an id of "layout"):
LinearLayout layout = (LinearLayout)findViewById(R.id.layout);
boolean success = formIsValid(layout);
public boolean formIsValid(LinearLayout layout) {
for (int i = 0; i < layout.getChildCount(); i++) {
View v = layout.getChildAt(i);
if (v instanceof EditText) {
//validate your EditText here
} else if (v instanceof RadioButton) {
//validate RadioButton
} //etc. If it fails anywhere, just return false.
}
return true;
}
To apply the method by kcoppock recursively, you can change it to this:
private void loopViews(ViewGroup view) {
for (int i = 0; i < view.getChildCount(); i++) {
View v = view.getChildAt(i);
if (v instanceof EditText) {
// Do something
} else if (v instanceof ViewGroup) {
this.loopViews((ViewGroup) v);
}
}
}
If you are writing in Kotlin, Android Jetpack's Kotlin extensions (KTX) provide extension functions for iterating over a ViewGroup's children.
myViewGroup.forEach { ... }
myViewGroup.forEachIndexed { index, view -> ... }
Just add the dependency to your app. Check the link above to get the most up-to-date version.
implementation "androidx.core:core-ktx:1.2.0"
These extensions contains hoards of useful functions otherwise chalked up as boilerplate. Worth checking out now to save time in the future!
Your onClickListener supplies the View v object; use View rV = v.getRootView() to position yourself on the form. Then use rV.findViewWithTag( ... ) or rV.findViewByID(R.id. ... ) to locate your form elements.