getSelectedItem from Spinner inside custom ListView element - java

I googled alot for this with no result. I have a custom ListView, every element has few TextViews and 3 Spinners and button. When I set values on spinners and press a button I want to get selcted values from those spinners and send them to a server. Everything works fine for list elements from top to the last visible element but on items that are not visible or visible in half 2 bad things happen.
If I change value on spinner, press button to save, 2 things happen depedning on which element I work on:
If element was half, or a little visible on activity load and I do those steps on it the value that is passed is the value that was set before I changed it.
If element wasn't visible at all and I do steps on it app crashes with NullPointerException linking the error to the declaration of a Spinner.
Code:
Adapter:
public View getView(final int position, View convertView, final ViewGroup parent) {
StudentList students = studentList.get(position);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
final View view = inflater.inflate(R.layout.student_list, null);
TextView id = (TextView) view.findViewById(R.id.list_id);
TextView name = (TextView) view.findViewById(R.id.list_name);
TextView surname = (TextView) view.findViewById(R.id.list_surname);
Spinner t1 = (Spinner) view.findViewById(R.id.list_t1);
Spinner t2 = (Spinner) view.findViewById(R.id.list_t2);
Spinner t3 = (Spinner) view.findViewById(R.id.list_t3);
TextView final = (TextView) view.findViewById(R.id.list_final);
Button save = (Button) view.findViewById(R.id.save);
id.setText(students.getId());
name.setText(students.getName());
surname.setText(students.getSurname());
final.setText(students.getFinal());
for (int i=0;i<t1.getCount();i++){
if (t1.getItemAtPosition(i).toString().equalsIgnoreCase(students.getT1())){
t1.setSelection(i);
}
}
for (int i=0;i<t2.getCount();i++) {
if (t2.getItemAtPosition(i).toString().equalsIgnoreCase(students.getT2())) {
t2.setSelection(i);
}
}
for (int i=0;i<t3.getCount();i++){
if (t3.getItemAtPosition(i).toString().equalsIgnoreCase(students.getT3())){
t3.setSelection(i);
}
}
if(t1.getSelectedItemPosition() > 1){
t2.setEnabled(false);
t3.setEnabled(false);
} else if (t2.getSelectedItemPosition() > 1){
t3.setEnabled(false);
}
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((ListView) parent).performItemClick(v, position, 0);
}
});
if(studentList.get(position).getProtokol().equals("open")){
} else {
t1.setEnabled(false);
t2.setEnabled(false);
t3.setEnabled(false);
save.setEnabled(false);
}
return view;
}
onCreate:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
long viewId = view.getId();
Spinner t1 = (Spinner) parent.getChildAt(position).findViewById(R.id.lista_termin1);//There the app crashes if I do things I described above
Spinner t2 = (Spinner) parent.getChildAt(position).findViewById(R.id.lista_termin2);
Spinner t3 = (Spinner) parent.getChildAt(position).findViewById(R.id.lista_termin3);
if (viewId == R.id.save) {
String t1Itemn = t1.getSelectedItem());
String t2Itemn = t2.getSelectedItem());
String t3Itemn = t3.getSelectedItem());
//Code that sends those string to the server based on urlConnection - works perfectly fine)
}
}
});

I was googling for 2 days and finally decided to post here, but 1h later I found the solution here. Changed all spinners like this:
Spinner t1 = (Spinner) parent.getChildAt(position-parent.parent.getFirstVisiblePosition()).findViewById(R.id.lista_termin1);

Related

how can I update ArrayAdapter data individually in Android

I want to update in and ArrayAdapter a TextView when user will click + or - button. I cannot figure out how can I change data of individual in ArrayApapter.
Here is a image for better explanation what I want to do :
public View getView(int position, View countView, ViewGroup parent) {
View listView = countView;
if (listView == null) {
listView = LayoutInflater.from(getContext()).inflate(R.layout.listview, parent, false);
}
word currentWord = getItem(position);
TextView foodName = (TextView) listView.findViewById(R.id.food);
Button minus = (Button) listView.findViewById(R.id.minus);
Button add = (Button) listView.findViewById(R.id.add);
TextView total = (TextView) listView.findViewById(R.id.total);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
return listView;
}
Whenever you are making a change through onclicklistener then just only change your data. like if your are using ArrayList> then just change the any value whatever you want like if your press 4th element with add+ then get the 4th item from the list and set it to +1. and then refresh your adapter with notifydatasetChanged().
In the above code you are only showing the UI part in the list whenever you will use data with you can do it then very easily.
Inside onClickListener, Increase or decrease the quantity and call onDataSetChanged().

Setting ImageView at certain positions in a ListView based on CheckBox

So I have a List View that when you click on a row it opens up a new activity. In the new activity there's a checkbox. If you check the check box and then go back to the listview activity it should set a checkmark next to the list view item that was initially clicked.
Whats happening right now is when I check the checkbox and return to the listview every row has a checkmark next to it regardless of which row the checkbox was checked from.
heres my mainactivity with the listview and on click listener that starts the second checkbox activity
//fill list view with xml array of routes
final CharSequence[] routeListViewItems = getResources().getTextArray(R.array.routeList);
//custom adapter for list view
ListAdapter routeAdapter = new CustomAdapter(this, routeListViewItems);
final ListView routeListView = (ListView) findViewById(R.id.routeListView);
routeListView.setAdapter(routeAdapter);
routeListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int listViewItemPosition = position;
CharSequence route = routeListViewItems[position];
int imageId = (int) image.getResourceId(position, -1);
if (route.equals(routeListViewItems[position]))
{
Intent intent = new Intent(view.getContext(), RouteDetails.class);
intent.putExtra("route", routeDetail[position]);
intent.putExtra("imageResourceId", imageId);
intent.putExtra("routeName", routeListViewItems[position]);
intent.putExtra("listViewItemPosition", listViewItemPosition);
startActivity(intent);
}
}
}
);
}
then heres what im passing from the second activity back to the listview activity
#Override ///////for back button///////
public void onBackPressed() {
super.onBackPressed();
////////sets checkmark next to listview item//////
if (routeCheckBox.isChecked())
{
Intent check = new Intent(RouteDetails.this,MainActivity.class);
check.putExtra("checkImageResource", R.drawable.checkmark);
check.putExtra("listViewItemPosition", listViewItemPosition);
startActivity(check);
}
}
and heres back in my listview activity where I recieve the info from my checkbox activity and set the checkmark
edited to include full adapter class
edited to include code that I found to solve my issue!
class CustomAdapter extends ArrayAdapter<CharSequence> {
public CustomAdapter(Context context, CharSequence[] routes) {
super(context, R.layout.custom_row ,routes);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater routeInflater = LayoutInflater.from(getContext());
View customView = convertView;
if(customView == null){customView = routeInflater.inflate(R.layout.custom_row, parent, false);}
CharSequence singleRoute = getItem(position);
TextView routeText = (TextView) customView.findViewById(R.id.routeText);
routeText.setText(singleRoute);
/////////////set check mark/////////////
ImageView checkImageView = (ImageView) customView.findViewById(R.id.checkImageView);
int checkImageResourceId = ((Activity) getContext()).getIntent().getIntExtra("checkImageResource",0);
int listViewItemPosition = ((Activity) getContext()).getIntent().getIntExtra("listViewItemPosition",0);
/////my solution was just setting where listviewitemposition == position in my getview method//////
if (listViewItemPosition == position)
{
checkImageView.setImageResource(checkImageResourceId);}
//////////////////////////////////////////////////
return customView;
}
thanks for any help!
The solution was I just needed use an if statement to set listviewItemPosition == position in my getView method
/////my solution was just setting where listviewitemposition == position in my getview method//////
if (listViewItemPosition == position)
{
checkImageView.setImageResource(checkImageResourceId);}
//////////////////////////////////////////////////

How can I individually validate the selected option in multiple RadioGroups within a ListView?

I'm very new to Android dev and programming in general. My goal is to create a quiz in this format.
Each row is a custom view that includes a RadioGroup with 3 RadioButtons. And that is working fine, as you can see in the picture.
This is how the List is being populated:
private void populateListView() {
ArrayAdapter<QuizQuestion> adapter = new MyListAdapter();
ListView list = (ListView) findViewById(R.id.questionsListView);
list.setAdapter(adapter);
}
private class MyListAdapter extends ArrayAdapter<QuizQuestion> {
public MyListAdapter() {
super(ShortQuiz.this, R.layout.item_view, myQuestions);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
if (itemView == null) {
itemView = getLayoutInflater().inflate(R.layout.item_view, parent, false);
}
QuizQuestion currentQuestion = myQuestions.get(position);
ImageView imageView = (ImageView) itemView.findViewById(R.id.item_icon);
imageView.setImageResource(currentQuestion.getImageId());
//Question
TextView question = (TextView) itemView.findViewById(R.id.item_question);
question.setText(currentQuestion.getQuestion());
//Game
TextView game = (TextView) itemView.findViewById(R.id.item_game);
game.setText(currentQuestion.getGameName());
//Option A
TextView optionA = (TextView) itemView.findViewById(R.id.item_radioA);
optionA.setText(currentQuestion.getOptionA());
//Option B
TextView optionB = (TextView) itemView.findViewById(R.id.item_radioB);
optionB.setText(currentQuestion.getOptionB());
//Option C
TextView optionC = (TextView) itemView.findViewById(R.id.item_radioC);
optionC.setText(currentQuestion.getOptionC());
return itemView;
}
}
The problem is that I do not know how to 'access' (set/get ids) each RadioGroup after creation in order to validate for right or wrong answers, which I want to do in one go pressing a button, as in: If the selected option is correct then +1 to Correct Answers.
Thanks.
Use a ViewHolder for each row. https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html
You can reference the items in each individual row. You can search for examples for how the ViewHolder is used in practice, but in general each row in the holder will be stored with a setTag() and retreived with a getTag(). So you can obtain the items in a view like:
view.getTag();

Cannot get listitems to reload from database

I have written a small app that has a ListView with a custom adapter. Each row contains some Buttons, which will change background color when clicked, and I got the list items to be clickable as well by putting
android:descendantFocusability="blocksDescendants"
in the xml of the list items. But now I have this weird bug where clicking on the list item reverts all clicked Buttons back to their original colorless state. How can I get the Buttons to keep their color?
Details:
Part of the custom adapter:
View.OnClickListener onButtonClicked = new View.OnClickListener() {
#Override
public void onClick(View button) {
View listItem = (View) button.getParent();
final long DBid = (long) listItem.getTag();//database ID
final Button b = (Button) button;
sqldataDataSource datasource = new sqldataDataSource(context);
datasource.open();
datasource.updateButton(DBid);
datasource.close();
b.setBackgroundColor(0xFF386F00);
}
};
As you can see, I change the background color AND change the database entry, so when the whole list is reloaded, the Button keeps its color (another part of my custom adapter):
public View getView(int i, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.hrlistitems, parent, false);
Button b = (Button) rowView.findViewById(R.id.HRlistB);
b.setOnClickListener(onButtonClicked);
if(!(values.get(i).getB().equals(""))){
b.setBackgroundColor(0xFF386F00);
}
return rowView;
}
This works fine when going to another activity and coming back to this one. The buttons are created colored as expected.
So my guess was that the list is recreated from the original listItem array when an item is clicked, which is why I tried to fix this by reloading my database, like so (from my activity):
#Override
protected void onStart() {
super.onStart();
datasource = new sqldataDataSource(this);
datasource.open();
listItems = datasource.getOnlyRoutes(id);//this works fine
Collections.sort(listItems, HallenRoute.vergleichen());
if (mListView == null) {
mListView = (ListView) findViewById(R.id.listViewHalle);
}
adapter=new customAdapter(this, listItems);
setListAdapter(adapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int pos, long nid) {
listItems.get(pos).increaseCount();
datasource.updateCountHR(listItems.get(pos));
listItems = datasource.getOnlyRoutes(id);//fix I tried, doesn't work
Collections.sort(listItems, HallenRoute.vergleichen());
adapter.notifyDataSetChanged();
}
});
}
But this doesn't work.
How can I get the ListView to either not reload on ItemClick or reload properly (i.e. from database)?
You don't have to reload the whole data for every Button click.
In your Button click you're just updating the data base and not your adapter dataset values, this is why you always get the old background color.
public View getView(int i, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.hrlistitems, parent, false);
Button b = (Button) rowView.findViewById(R.id.HRlistB);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View button) {
View listItem = (View) button.getParent();
final long DBid = (long) listItem.getTag();//database ID
final Button b = (Button) button;
sqldataDataSource datasource = new sqldataDataSource(context);
datasource.open();
datasource.updateButton(DBid);
datasource.close();
//b.setBackgroundColor(0xFF386F00); no need for this line, getView() method will take care of the background
//update your adapter dataset, eg: values.get(i).setB("newColor");
notifyDataSetChanged(); // to refresh your adapter
}
});
if(!(values.get(i).getB().equals(""))){
b.setBackgroundColor(0xFF386F00);
}
return rowView;
}
PS: It's better if you save your "database ID" in your Model object not as a View tag.

Android get Textview text on the same row of listview

I have this code inside my BaseAdapter Adapter:
public View getView(final int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.facebook_friends_layout, null);
TextView friendsName = (TextView)vi.findViewById(R.id.tvFacebookName); // Friends thumb
friend_image=(ImageView)vi.findViewById(R.id.ivFacebookPicture); // thumb image
song= new HashMap<String, String>();
song = data.get(position);
friendsName.setText(song.get(MyFriends.KEY_FBNAME));
//Log.i("Facebook Pangalan", ""+MyFriends.KEY_FBNAME);
FriendName = (String) friendsName.getText().toString();
FBID = song.get(MyFriends.KEY_FBID);
String fbAvatarUrl = "http://graph.facebook.com/"+ FBID +"/picture";
//Log.i("FBID", FBID);
BitmapManager.INSTANCE.loadBitmap(fbAvatarUrl, friend_image, 100,100);
Button btn=(Button)vi.findViewById(R.id.btnAdd);
if (FBID.equals(""))
{
btn.setVisibility(View.GONE);
}
else
{
btn.setVisibility(View.VISIBLE);
}
btn.setOnClickListener(new OnClickListener(){
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//FACEBOOK FRIENDS
Log.i("", ""+FriendName);
//AddfromFacebookFriends();
}
else if (LOCK_BASEDATA.equals("1"))
{
//MY REQUEST
//((MyFriends)context).SetMyRequest();
//Log.i("LangYa", "Langya");
}
else if (LOCK_BASEDATA.equals("2"))
{
//FRIEND REQUEST
//((MyFriends)context).SetFriendRequest();
//d2papasok
AddFriendRequest();
}
}
});
return vi;
}
I am logging my friend's name whenever I click on the button. Now my problem starts when I click the button; I am not getting my desired string. It is getting the string from another row of my listview.
EDIT
Thanks, actually ive just aaded this code
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//Object x =btn.getTag();
//String sa = x.toString();
View parentView = (View) arg0.getParent();
String textviewtext = ((TextView) parentView.findViewById(R.id.hiddentv)).getText().toString();
//FACEBOOK FRIENDS
AddfromFacebookFriends(textviewtext);
}
else if (LOCK_BASEDATA.equals("1"))
{
I am just getting my parents View to get my desired textview and now it works. Thanks anyway
You are trying to get the FriendName using this code:
TextView friendsName = (TextView)vi.findViewById(R.id.tvFacebookName);
FriendName = (String) friendsName.getText().toString();
This is not The FriendName of the ListView item you clicked. Its the FriendName of the newly created ListView item. Because in getView(), the ListView item you get is the newly created one.
One way to solve this is:
Use tags like KunalK suggested. I am not sure if it works...i never tried it.
Or the other way is:
onButtonClicked get the Position of the ListView item you clicked, and get the respective Name from the ArrayList you are using.
Here the Position is not the position parameter in the getView(). That gives the position of the newly created ListView item again.
Use this to get the actual position of the clicked item:
int clickedItemPosition = yourListView.getPositionForView((View) yourButton.getParent());
you should go with this by setting the "FriendName" in your button's setTag property. and whenever you handle your button click event fetch your FriendName String by using getTag property of button. for e.g. something like this:
....
btn.setTag(FriendName);
btn.setOnClickListener(new OnClickListener(){
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//FACEBOOK FRIENDS
Log.i("", ""+btn.getTag().toString());
//AddfromFacebookFriends();
}
else if (LOCK_BASEDATA.equals("1"))
{
//MY REQUEST
//((MyFriends)context).SetMyRequest();
//Log.i("LangYa", "Langya");
}
else if (LOCK_BASEDATA.equals("2"))
{
//FRIEND REQUEST
//((MyFriends)context).SetFriendRequest();
//d2papasok
AddFriendRequest();
}
}
});
....
Getting the name from the list can be accompished by using an onListItemClick method as follows (not in your adapter, but in the class with your list):
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
TextView friendsName = (TextView)v.findViewById(R.id.tvFacebookName);
FriendName = (String) friendsName.getText().toString();
}
Since this code is the onListItemClick method, the View v parameter is the view of the row you clicked. Once you have that, you search that particular row view for the TextView you want and then pull the string from that.
You had the right idea, you just put it in the wrong place.

Categories