Android - attach data to views - android

In my application I create dynamic rows in table much as in this tutorial:
http://en.androidwiki.com/wiki/Dynamically_adding_rows_to_TableLayout
for(int i = startDay; i < startDay + 7; i++){
/* Create a TextView to be the row-content. */
TextView day = new TextView(this);
day.setText(Integer.toString(i));
day.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
day.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i("Listener: ", "Click");
}
So now when I click on a TextView I can register click event, but how do I determine which TextView was clicked?
Not just an object which I get with an event but data like which day number was clicked?
Ideally I would want to have data attached to every view I create dynamically.
Something like data() method in Javascript jQuery.
Right now I can see only 1 way to solve this - while creating TextView add id with data and when clicked - get id back and parse it to get my data. But it strikes me as ugly approach.
Is there a way to attach arbitrary data to android views?

Found answer going through view methods. Maybe it will be useful for someone.
Methods I needed were:
setTag() and getTag()
http://developer.android.com/reference/android/view/View.html#setTag%28java.lang.Object%29

Related

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.

filling in text views from shared preferences in a scroll view

Im a bit stuck on the best way to implement this so here I am.
I have a list of shared preferences with a label and a price. My app, a sort of calculator if you will, I would like to load the shared preferences in this way but stuck on how to implement it properly so ill wrote it down in a very literal way
Load shared preferences "item1"
Load into textView1 if empty
if it is full then try textview2,
if it is full then try textview3,
etc etc
I would like a function which loads preference 1, attempts to load it into a view and if its full, try the next textview and so on until it finds and empty slot. and then try the next shared preference item
Maybe I'm looking at this wrong but without writing out tons of if/else statements to get the job done, I cant see a way that makes sense.
I've seen somewhere some code to increment the textview numbers in a loop until a case is met but cant seem to recall it anywhere. this would reduce the code a lot if this was implemented properly I'm sure.The app I'm creating will display a list of selected items from another screen,save selected to shared preferences and then load the list on the results screen to give a total based on the sums attached to the items loaded.
I have no actual code to give you as im still prototyping this section and have nothing solid to show you.
any pointers welcome or any nod in the right direction would be handy.
thanks guys
You could add TextViews dynamiclly through java.
public class DynamicAvtivity1 extends Activity {
TextView tv;
EditText et;
Button btn;
LinearLayout ll;
int i;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
i = 1;
ll = new LinearLayout(this);
ll.setOrientation(1);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT , LayoutParams.FILL_PARENT);
final LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT , LayoutParams.WRAP_CONTENT);
ll.setLayoutParams(lp);
tv = new TextView(this);
tv.setText("Enter Name");
tv.setLayoutParams(lp2);
ll.addView(tv);
et = new EditText(this);
et.setHint("Name");
et.setLayoutParams(lp2);
ll.addView(et);
btn = new Button(this);
btn.setLayoutParams(lp2);
btn.setText("Add Button");
btn.setLayoutParams(lp2);
ll.addView(btn);
btn.setOnClickListener(new View.OnClickListener() {
#SuppressLint("NewApi") #Override
public void onClick(View v) {
// TODO Auto-generated method stub
Button b = new Button(getApplicationContext());
b.setLayoutParams(lp2);
b.setText("Button " + i++);
b.setTextColor(Color.BLACK);
b.setBackground(btn.getBackground());
ll.addView(b);
}
});
setContentView(ll);
}
}

Android: Dynamically create image button with click event

I'm new to android and I require to have a list of image buttons in an activity which are created based on the data in a database. I haven't created anything like this in android before and so far I've been using HTML tables to show my data in a grid view. I'm not asking for any special code, I'm just clueless on how to implement this. I wanna know what the best approach is.
One problem I've faced is with the click events(in the way I've been doing them so far) which do not take in any EventArg, so I can't get the name of the button out of them.
If you're sure that the OnClickListener instance is applied to a Button, then you could just cast the received view to a Button and get the text:
public void onClick(View v) {
// 1) Possibly check for instance of first
Button b = (Button)v;
String buttonText = b.getText().toString();
}
// create the layout params that will be used to define how your button will be displayed
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// Create Button
final Button btn = new Button(this);
// Give button an ID
btn.setId(someinteger);
btn.setText("Add Text");
// set the layoutParams on the button
btn.setLayoutParams(params);

Different On-clicks for programmatically added buttons

I was looking through some topics but couldn't find exact answer or at least couldn't get it right. What happens in the code is that i create one button for each row in my database and each button is supposed to have an OnClick that sends us to another activity along with some values(each button is supposed to have different value) but in the end it seems like i get the same value for all of my buttons which makes me think that it only creates 1 view for all of the buttons.
Cursor przepis = bazaUzytkownikow.rawQuery("SELECT * FROM przepisy", null);
int liczba_wierszy = przepis.getCount();
przepis.moveToPosition(0);
for (int i = 0; i < (liczba_wierszy/4)+1; i++) {
LinearLayout row = new LinearLayout(this);
row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
for (int j = 0; j < 4; j++) {
if((przepis.moveToPosition((i*4)+j)!=false))
{
nrPrzepisu=(i*4)+j;
Button btnTag = new Button(this);
btnTag.setLayoutParams(new LayoutParams(115, 60));
btnTag.setText(przepis.getString(przepis.getColumnIndex("nazwa")));
btnTag.setTextSize(10);
btnTag.setId(j + 1 + (i * 4));
btnTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View t) {
// TODO Auto-generated method stub
Intent IdzPrzepis = new Intent(getApplicationContext(), DodajPrzepis.class);
IdzPrzepis.putExtra("ID_uzytkownika", ID_uzytkownika);
IdzPrzepis.putExtra("nr_Przepisu", nrPrzepisu);
startActivity(IdzPrzepis);
}
});
row.addView(btnTag);
}
}
layout.addView(row);
}
To make the code more clear for you - bazaUzytkownikow is my database, liczba_wierszy is the number of the rows that i got. I move the cursor to the beginning since it's where i want to start and i proceed to "cut" my data using 2 loops. I am aiming for 4 buttons in 1 row.
The part that i think doesn't work is the OnClick method where i want my button to switch activity and send nrPrzepisu which is basically adding a connection between my button and proper row in the database (In the other activity i want to set text, reading rows from database depends on which button you click).
I checked the other activity and it seems to be reading same nrPrzepisu everytime which usually equals the last value of nrPrzepisu=(i*4)+j when loops finish and it made me think that i somehow need to make different views for each button.
you are passing the same object to each onClick then changing that object with the next iteration. In the end all the onClicks have the same nrPzepisu object and it is returning the value which is whatever is last in this example.
int nrPrzepisu = (i*4) + j;
This way you aren't passing the same object into all the onClicks.

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

Categories

Resources