I'm developing an app in Android in Kotlin, and in one activity I have 10 editText. How i could get the text of all editTexts within a for loop? EditTexts are into Constraint Layouts, which are into a Linear Layout.enter image description here
You can iterate over the child views of the parent view group and just gather the texts, something like this:
val parentView: ViewGroup = findViewById(R.id.parent)
for (i in 0 until parentView.childCount) {
val view: View = parentView.getChildAt(i)
if (view is EditText) {
Log.d("text", view.text.toString())
}
}
Change the R.id.parent to the correct id of course - the id of your constraint layout.
Related
Do you guys know if there's a proper manner to get all specific view types from the parent view as the title says?
I would like to get all the EditText views from my activity, so I wonder if there's a better way than using this solution get all views from an activity and then testing every view to check if it's an EditText or not?
Thank you for the help,
Florian
Approach 1 :
Let's say you named your edittext edittext_0, edittext_1, .. edittext_n. You can do:
ViewGroup vg = (ViewGroup) view;
for (int i = 0; i < n; i++) {
int id = vg.getResources().getIdentifier("edittext_"+i, "id", getPackageName());
edittext[i] = (EditText) vg.findViewById(id);
}
Actually the answers specified in the link given, are feasible if you have a large number of views, but if you want a specific type of view from a view/viewgroup, simply use findViewById method.
Example :
(in Kotlin) //Similar syntax in java
val view : View = findViewById(your_layout_or_any_other_view)
val childView : EditText = view.findViewById(edittext_id)
OPTIONAL READING
Optimised Answer for the answers given in link :
It is easier with Kotlin using for-in loop:
for (childView in ll.children) {
if(childView.id == your_edittext_id) //If required
//childView is a child of ll
}
//Here ll is id of LinearLayout defined in layout XML.
I'm using this line to check on a number of views in my app and get the values associated with them, as input by the user. Every other view (odd) is a text view that's used as a title for the following view. These are created dynamically at runtime, and so I've collected the IDs into an arrayList to use in the following loop:
for(id in data.orEmpty()) {
val mView = findViewById<View>(id)
if (mView is TextView) {
Log.d("BEAU - ", "WOOT! ID number $id TextView - ${mView.text}")
}
if (mView is EditText) {
Log.d("BEAU - ", "WOOT! ID number $id EditText - ${mView.text}")
}
if (mView is RatingBar) {
Log.d("BEAU - ", "WOOT! ID number $id RatingBar - ${mView.numStars}")
}
}
The problem I'm having is that every EditText is being counted as both a TextView and an EditText; and so I'll have something like this:
D/BEAU -: WOOT! ID number 1 TextView - General EditText
D/BEAU -: WOOT! ID number 2 TextView - Hello World
D/BEAU -: WOOT! ID number 2 EditText - Hello World
However, all of the other things (like the rating bar) work perfectly. So, the question is, why is EditText passing a type check for text view; and is there something I can do to check for only text views and not text views and edit texts in the first if statement?
EDIT:
Temporarily, I've been able to check against EditTexts when checking for TextViews. I've done this like so:
if (mView is TextView && mView !is EditText) {}
But, is this right to do, and if so why should I have to do it like this?
Yiu need to put your chcecks in the right order. In this case as EditText extends TextView, you need to check first if this is EditText and then check its parent class (if you have longer inheritance chain, then you should check from the bottom of the hierarchy up to base/root class.
It's because EditText is a subclass of TextView, so this will give you true -
EditText is TextView
In EditText class you can see -
class EditText extends TextView { ... }
If it is suitable you can compare classes instead of checking types:
when (view.javaClass) {
TextView::class.java, AppCompatTextView::class.java -> {}
EditText::class.java, AppCompatEditText::class.java -> {}
RatingBar::class.java, AppCompatRatingBar::class.java -> {}
}
I searched and found ways to make a single EditText not editable, such as
edittext.setKeyListener(null);
set EditText as android:focusable="false"
However, the problem with these methods is that I need to get references to each of the EditText views in my layout and individually implement the above statements. Is there a way by which I can make all EditText views in a layout not editable?
The application is this: I have a 'Display and Edit' activity, where the user is shown the current record in the database. At this point the displayed text should be read only. If required, he clicks an edit button and then the EditText views become editable.
I tried setting android:inputType="none" and android:focusable="false" in the root ViewGroup but that didn't work. Is there a way out?
If you want to achieve this programmatically,
public void setupUI(View view, boolean editable) {
if (view instanceof EditText) {
((EditText)view).setFocusable(editable);
//Here you can add any other code that needed to be done while changing focus of a particular edit text
return;
}
//If a layout container, iterate over children and seed recursion.
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View innerView = ((ViewGroup) view).getChildAt(i);
setupUI(innerView, editable);
}
}
}
Provide this method with your parent view of your fragment or activity.
When you are clicking edit button pass the parent view and true(i.e, editable) to the method and after editing pass parent view and false(i.e, not editable) instead.
From android:descendantFocusability docs:
Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.
Apply this to the parent of those EditTexts:
android:descendantFocusability="blocksDescendants"
This will result the ViewGroup to block its descendants from receiving focus.
I have added multiple TextViews dynamically in a layout,
for(int x=4;x<result.length();x++)
{
JSONObject collegeData = result.getJSONObject(x);
Log.i("Classlist",""+x);
TextView tv = new TextView(this);
Animation animation = AnimationUtils.loadAnimation(student_profile.this, android.R.anim.slide_in_left);
tv.startAnimation(animation);
tv.setTag(tag);
tv.setLayoutParams(lparams);
tv.setText(collegeData.getString("date") + " " + collegeData.getString("day_name"));
tv.setTextSize(17);
this.linearLayout_top5classes.addView(tv);
}
This loop adds textViews according to the data received by the url,Now i want to remove the textviews which were created in this loop and i cant find a proper method to do so....I only want to remove these textviews and not all the textviews
UPDATE
First i used
int prv=0;
then
String tag ="textView_"+x;
prv++;
in the first loop to generate multiple tags
then i removed them with
for(int x=4;x<prv;x++)
{
View view = this.linearLayout_top5classes.findViewWithTag("textView_"+x);
this.linearLayout_top5classes.removeView(view);
Log.i("prv value",prv+"");
}
Of course there is a way. Just look for child views with tag:
View view = this.linearLayout_top5classes.findViewWithTag(tag);
this.linearLayout_top5classes.removeView(view);
If you add ID's to child views, then:
View view = this.linearLayout_top5classes.findViewById(id);
this.linearLayout_top5classes.removeView(view);
If possible try using different layout for the dynamically added textviews. and then remove views from second layout only. By using,:
linearLayout_top5classes.removeAllViews();
To remove particular view with tag
View view = this.linearLayout_top5classes.findViewWithTag(tag);
this.linearLayout_top5classes.removeView(view)
To remove view from particular position
this.linearLayout_top5classes.removeViewAt(position);
Use following logic to remove any view from layout.
this.linearLayout_top5classes..post(new Runnable() {
public void run() {
this.linearLayout_top5classes..removeView(view);
}
});
In my Android app there is a requirement that a number of UI elements should be disabled until a button click carryout. Can I disable all the UI elements in a layout by referring the layout without disable them one by one. Is it possible.Can some one help me.
You could disable all views recursively like this.
Just pass the layout as view to the method:
private void enableViews(View v, boolean enabled) {
if (v instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) v;
for (int i = 0;i<vg.getChildCount();i++) {
enableViews(vg.getChildAt(i), enabled);
}
}
v.setEnabled(enabled);
}
Just run enableViews(view, false) to disable, or enableViews(view, true) to enable again.
use following attribute in your xml layout( as a example textView)
android:visibility="gone"
in button click event
myText.setVisible(myText.VISIBLE)
you can either use them one by one or you can put all invisible content in a single layout and hide the layout. then once you want to show them, just VISIBLE the layout. then all will display
need any more comment.. just comment.