get array of TextViews - android

I'm making an app that stores results in a multiple textviews,
First, I need to get the views, they are 20 views named result 1, .... result 20.
how can i get them to an array of textview.
I found this method but it's too long
TextView [] results = {(TextView)findViewById (R.id.result1),
(TextView)findViewById (R.id.result2),(TextView)findViewById (R.id.result3),
(TextView)findViewById (R.id.result4),(TextView)findViewById (R.id.result5),
(TextView)findViewById (R.id.result6).....};
thank you for help

How you started is correct, now think about putting that repetitive code in a cycle.
For example design a method that will take as the input an array of your TextView resources, and using a "for" cycle find that view by corresponding id.
private TextView[] initTextViews(int[] ids){
TextView[] collection = new TextView[ids.length];
for(int i=0; i<ids.length; i++){
TextView currentTextView = (TextView)findViewById(ids[i]);
collection[i]=currentTextView;
}
return collection;
}
And then you use it like this:
// Your TextViews ids
int[] ids={R.id.result1, R.id.result2, R.id.result3};
// The resulting array
TextView[] textViews=initTextViews(ids);

if you have a handle to parent the layout that contains the text views, you can recursively discover them with a function like this,
void getTextViews(View view, List<TextView> textViews) {
if (view instanceof TextView) {
textviews.add((TextView)view);
else if (TextView instanceof ViewGroup) {
getTextViews((ViewGroup)view, textViews);
}
}
now call it like this,
ViewGroup topLayout = findViewById(...);
List<TextView> views = new ArrayList<TextView>();
getTextViews(topLayout, views);
TextView[] textViewArray = textViews.toArray(new TextView[0]);
this is quite a bit longer, but it has the advantage of not needing to change the code if you add, remove, or rename a textview.
IMHO, don't focus on writing less code, focus on writing clear code. the speed at which you type is rarely the limiting factor in your productivity.

Related

Why TextView variable needs to be inside a loop

LinearLayout x=(LinearLayout)findViewById(R.id.english_no);
Why this code is wrong-
TextView wordview=new TextView(this);
for(int i=0;i<english.size();i++)
{
wordview.setText(english.get(i));
x.addView(wordview);
}
and this one is correct-
for(int i=0;i<english.size();i++)
{
TextView wordview=new TextView(this);
wordview.setText(english.get(i));
x.addView(wordview);
}
I couldn't understand the difference.
here in the first example you are just referring to the first TextView that you created and changing its value and adding it to the view, eventually the x (hoping a Linearlayout) will have english.size() number of views where the content of every view would be same and that is the last content of english

Remove items from array with auto generated onclick

I create a vertical list of textviews with an arraylist and attach on onclicklistener to each one. In the onclick I set code to remove that item. When I click in sequence from the last generated to the first this works fine. But if I remove the first one and then the last one it gives me a null pointer exception. I know this is happening because it is attempting to remove an index that is no longer present, or at least that is what I think is happening. But I cannot figure out how to solve that.
private void generateViews(){
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
final TextView[] textView = new TextView[questionArray.size()];
for(int i = 0; i < questionArray.size(); i++){
final int Index = i;
textView[Index] = new TextView(getActivity());
textView[Index].setText(questionArray.get(i));
textView[Index].setId(Index);
textView[Index].setGravity(Gravity.CENTER);
textView[Index].setPadding(15,15,15,15);
textView[Index].setLayoutParams(params);
textView[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (textView[Index].getId() == (v).getId()) {
questionArray.remove(Index);
answerArray.remove(Index);
saveVariables();
updateViews();
((ViewGroup) textView[Index].getParent()).removeView(textView[Index]);
Toast.makeText(getActivity(), "Question and Answer removed!", Toast.LENGTH_SHORT).show();
}
}
});
mainLayout.addView(textView[Index]);
}
EDIT:
I figured out a small fix but it has it's problems. Instead of removing the items from the arrays with the index I can remove them by searching for the text within the textview.
The problem with this solve is that if my array contains 2 items that are identical then it may remove the wrong index.
questionText = textView[Index].getText().toString();
answerText = textView[Index].getText().toString();
if(questionArray.contains(questionText) && questionArray.size() > 0){
questionArray.remove(questionText);
answerArray.remove(answerText);
}
Solved:
I solved it by first searching for the index of the question text and removing that index from both arrays. The arrays are user generated and I plan on preventing the user from entering the same question twice.
questionText = textView[Index].getText().toString();
int questionIndex = questionArray.indexOf(questionText);
questionArray.remove(questionIndex);
answerArray.remove(questionIndex);
Also, I did it this way because I am still an amateur and was not aware of the Recyclerview. I plan on educating myself on that function and hopefully implementing it.
I really have no idea about why you want do this? if you just want remove textview in a list , why don't you use listview or recyclerview instead ?
You should consider using RecyclerView.

How to change the text within multiple buttons?

I'm trying to convert a c# windows form program over to android and I'm at the very last piece that I can't seem to figure out the translation for.
I have 9 buttons in a framelayout that I need to remove the text from either by iterating or by grabbing all at once.
In my original program I used a foreach loop like this:
foreach(control boardPosition in gameBoard)
{
((Button) boardPosition).Text ="";
((Button) boardPosition).ForeColor = Color.Black;
}
This is what I've gotten so far
FrameLayout GameBoard = (FrameLayout) findViewById(R.id.GameBoard)
for(Button boardPosition : GameBoard)
{
boardPosition.setText("");
boardPosition.setTextColor(Color.BLACK);
}
The error that I'm receiving is just "foreach not applicable to type 'android.widget.Framelayout' "But I'm not sure whats it's replacement or if it has one.
The object you are looping against must implement iterable interface. Java must know that it can be iterated in some kind. FrameLayout is not iterable. It doesn't know your intentions that you have array of buttons in it.
For looping every button in layout I would use something like this:
FrameLayout layout = (FrameLayout) view.findViewById(R.id.frame);
int children = layout.getChildCount();
for (int i = 0; i < children; i++) {
View view = layout.getChildAt(i);
if (view instanceof Button) {
((Button) view).setText("");
((Button) view).setTextColor(Color.BLACK);
}
}
If you still want to use foreach cycle, you must extend FrameLayout class and implement Iterable interface. But it's more work over nothing.

onPause() & onSaveInstanceState() for created UI

First off I have searched for this info for about a week and found very little. So hopefully this long read helps some other new people.
I have created a UI from JSON. This UI has all kinds of Views. Such as EditText, RadioButton, CheckBox, Spinner, etc. Now I need to account for certain inevitable scenarios. Screen rotation, phone call, back button, home button etc. Since all these Views are created after a network call/response and this takes time I do not want to repeat this action each time. So saving the actual RadioButton or EditText and what was selected on the RadioButton or typed into the EditText is extremely important. From what I've read for screen rotation I use onSaveInstanceState(). For anything else I would use onPause() because it is the only thing that is garunteed to be called.
The problem is I have no idea how to store programatically created Views with no id's in sharedprefs or a bundle let alone the values they hold. Lets look at my code and then discuss what I think is currently possible.
allEdit = new ArrayList<EditText>();
else if (map.get(TAG_FIELD).equals(et)) {
Log.v("RESPONSE", "About to create an EditText");
// find
LinearLayout content = (LinearLayout) getActivity()
.findViewById(R.id.add);
// create
TextView tv = new TextView(getActivity());
EditText et = new EditText(getActivity());
LinearLayout ll1 = new LinearLayout(getActivity());
// set
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT));
et.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
ll1.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
tv.setText(map.get(TAG_NAME));
ll1.setOrientation(LinearLayout.HORIZONTAL);
// add
ll1.addView(tv);
ll1.addView(et);
allEdit.add(et);
content.addView(ll1);
}
So in the example above I have created an EditText and stored it in an ArrayList<EditText>. Now my thought is that in onPause() I could do something like this.
for (int i = 0; i < allEdit.size(); i++) {
EditText et = allEdit.get(i);
String input = et.getText().toString();
prefsEdit.put(input);
}
Which I think might work, it also might overwrite the String "input" inside shared preferences over and over again. Not totally sure how that works. It also still does not solve how to save the actual EditText so that it does not have to be recreated.
Now in onSavedInstanceState() I think I may be able to get away with just inserting the whole ArrayList<EditText> as serializable, right? Like this...
putSerializable("key", allEdit)
However that does not save the values inside them.
So how do I save these Views and their values in onSavedInstanceState() and onPause()? Perhaps more importantly, do I need both? Can I get away with just using onPause()?
Thank you
I havent tried this, but it sounds like it would work in practice. When creating the activity (before the JSON populates) create your own ViewGroup. From there, read the JSON and add every view that you get to the VeiwGroup. Then, when you want to save the information or whatever do this
int viewCount = mViewGroup.getChildCount();
for(i=0;i<viewCount;i++) {
newView = mViewGroup.getChildAt(i);
if (newView instanceOf EditText) {
EditText newEditText = (EditText)newView
string value = newEditText.getText();
}
else if (newView instanceOf RadioButton) {
same as above ^
etc...
}
}
Then, for each of the values you pull add them to an array, maybe even a NamedPair to store their ID and value (by ID I mean index of which view it is). So
public List<String> lstEditTextValues = new ArrayList<String>();
After all that is said and done, then you can itterate through each one, and save it as an individual value through the bundle, save in a shared pref, or put into a static class level variable (not the safest way to retain information, but does work).
Hope this helps. Let me know if im completely off topic

dynamically name textview after inflating android

I m inflating 4 linear layouts multiple times in a scroll view. Each layout has a title in its header. The code snippet is given below.
for(int j=0;j<qType.length;j++)
{
LinearLayout.LayoutParams siz = new LinearLayout.LayoutParams(width, height);;
if(qType[j]==0)
{
view1 = getLayoutInflater().inflate(R.layout.layout1, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/3);
}
else if(qType[j]==1)
{
view1 = getLayoutInflater().inflate(R.layout.layout3, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/3);
}
else if(qType[j]==2)
{
view1 = getLayoutInflater().inflate(R.layout.layout4, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/3);
}
else if(qType[j]==3)
{
view1 = getLayoutInflater().inflate(R.layout.layout5, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/2);
}
siz.topMargin = 25;
main_layout.addView(view1, siz);
}
scroll_layout.addView(main_layout);
scroll_layout.setBackgroundResource(R.drawable.options_background);
setContentView(scroll_layout);
Now there is textview in each layout and i want to change the text of it. If i access them by findviewbyid and give settext, only the first instance is being changed, i want to change the textview on all occasions.
for(int k=0;k<NumberQuestions.length;k++)
{
TextView number_title = (TextView)main_layout.findViewById(R.id.number_title);
TextView mcq_title = (TextView)main_layout.findViewById(R.id.mcq_title);
TextView comment_title = (TextView)main_layout.findViewById(R.id.comment_title);
TextView cam_title = (TextView)main_layout.findViewById(R.id.cam_title);
if(qType[k]==0)
{
number_title.setTypeface(myriadpro_bold);
number_title.setText(NumberQuestions[k]);
}
if(qType[k]==1)
{
comment_title.setTypeface(myriadpro_bold);
comment_title.setText(NumberQuestions[k]);
}
else if(qType[k]==2)
{
mcq_title.setTypeface(myriadpro_bold);
mcq_title.setText(NumberQuestions[k]);
}
else if(qType[k]==3)
{
cam_title.setTypeface(myriadpro_bold);
cam_title.setText(NumberQuestions[k]);
}
Please help.
probably the TextView android: id in all layouts are the same, thus explaining the behavior of the method findViewById always returns the first occurrence
Disclaimer: I feel like you are trying to work against the Android Framework, as opposed to working with it. My suggestion is a tad bit of an overhaul, but I do feel like it is the correct way to go about things.
I would recommend using a ListView, since you are repeating the same format many times. A listview will typically have a container of objects of objects, and an adapter responsible for mapping an object to a particular row within the listview. When you change the data in the underlying container, you will call the callback notifyDataSetChanged() for your adapter to notify it that you changed the underlying data and alert it to update your listview.
2 great resources/tutorials from the android developer site:
ListView: http://developer.android.com/guide/topics/ui/layout/listview.html
Adapters: http://developer.android.com/guide/topics/ui/declaring-layout.html#AdapterViews
If i am right main_layout is a name view in your xml file.So You should use like this
view1 = getLayoutInflater().inflate(R.layout.layout1, main_layout,false);
TextView tv = (TextView)main_layout.findViewById(R.id.tv1);
where tv is texview in layout1.xml

Categories

Resources