how to maintain inflated radio button state in listView - android

So I have a listView that I'm populating with a static xml, but inside that xml I have a dynamic container that I inflate items into when the user clicks on an item in the listView.
Basically the view(s) I'm inflating looks like (x) amount of radio buttons and a textView.
The reason I have to do it this way is that the amount of radio buttons inflated could change depending on what type of list item it is.
The issue I'm running into is that once the radio buttons are inflated and the user selects a button, the list doesn't save the state from which the user last selected the radio button. Or rather, it recycles the radio button state to another position in the list. Which is somewhat correct since that's what listview does. I want it to only save the user selected answer at the position they selected in the listView.
I've been working on this for about a week and can't find a good solution. If anyone would like to help I'd greatly appreciate it. I'll post the relevant code below.
SurveyView (Custom container to inflate views into)
public class SurveyView extends LinearLayout {
private LinearLayout pollContainer;
private Context context;
private String type;
private int numOfAnswers;
private ListView answersList;
private ArrayList<String> answers;
private boolean visibility = true;
private OnClickListener listener;
private ArrayList<View> options;
private static int tag = 88888888;
private ArrayList<Boolean> checked;
private Integer[] percent = {33, 25, 15, 20, 7};
private int position;
/**
* #param context the context of the activity
* #param type the type of poll
* #param numOfAnswers if the poll is multiple choice (most likely) provide number of answers.
*/
public void setLayout(final Context context, String type, int numOfAnswers, final int position) {
this.type = type;
this.numOfAnswers = numOfAnswers;
this.context = context;
this.position = position;
switch (type) {
case "Multiple":
if (visibility) {
for (int i = 0; i < numOfAnswers; i++) {
View v = LayoutInflater.from(getContext()).inflate(R.layout.poll_multiple_choice_answers_row, null);
View space = LayoutInflater.from(getContext()).inflate(R.layout.space, null);
v.setTag(tag);
options.add(v);
final RadioButton rb = (RadioButton) v.findViewById(R.id.answer_voted_button);
rb.setClickable(false);
rb.setFocusable(false);
tag++;
addView(v);
addView(space);
}
}
break;
case "Slider":
break;
case "Tree":
break;
case "Sentiment":
break;
}
}
public SurveyView(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
options = new ArrayList<>();
}
public boolean isVisibility() {
return visibility;
}
public void setVisibility(boolean visibility) {
this.visibility = visibility;
}
public void setAnswers(int position) {
RadioButton rb;
for (int i = 0; i < options.size(); i++) {
if (i != position) {
rb = (RadioButton) options.get(i).findViewById(R.id.answer_voted_button);
rb.setChecked(false);
}
else {
rb = (RadioButton) options.get(position).findViewById(R.id.answer_voted_button);
rb.setChecked(true);
for (int p = 0; p < options.size(); p++) {
TextView answer = (TextView) options.get(p).findViewById(R.id.poll_answer);
answer.setText("Abraham Lincoln");
TextView tv = (TextView) options.get(p).findViewById(R.id.answer_percent);
tv.setText(Integer.toString(percent[p]));
options.get(p).setBackground(new PercentDrawable(percent[p], context.getResources().getColor(R.color.icitizen_poll_opaque_gold)));
}
}
}
}
Adapter for the listview
PollsAdapter extends BaseAdapter {
private LayoutInflater inflater;
private Context context;
private ArrayList<Card> data;
private ArrayList<RelativeLayout.LayoutParams> params;
private ArrayList<Integer> pollAnswers;
private int selectedPosition = 0;
public PollsAdapter(Context context, ArrayList<Card> data,
ArrayList<RelativeLayout.LayoutParams> params,
ArrayList<Integer> pollAnswers) {
this.context = context;
this.data = data;
inflater = LayoutInflater.from(context);
this.params = params;
this.pollAnswers = pollAnswers;
}
public static class ViewHolder {
TextView type;
TextView time;
TextView text;
TextView space;
TextView pollSpace;
ImageView type_icon;
SurveyView answerView;
RadioButton rb;
ArrayList<View> options;
private ViewHolder() {
}
private ViewHolder(TextView type, TextView time, TextView text, ImageView type_icon, SurveyView answerView) {
this.type = type;
this.time = time;
this.text = text;
this.type_icon = type_icon;
this.answerView = answerView;
}
public TextView getType() {
return type;
}
public void setType(TextView type) {
this.type = type;
}
public TextView getTime() {
return time;
}
public void setTime(TextView time) {
this.time = time;
}
public TextView getText() {
return text;
}
public void setText(TextView text) {
this.text = text;
}
public ImageView getType_icon() {
return type_icon;
}
public void setType_icon(ImageView type_icon) {
this.type_icon = type_icon;
}
public SurveyView getAnswerView() {
return answerView;
}
public void setAnswerView(SurveyView answerView) {
this.answerView = answerView;
}
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.polls_card_layout, null);
viewHolder.type = (TextView)convertView.findViewById(R.id.card_type);
viewHolder.time = (TextView)convertView.findViewById(R.id.card_poll_time);
viewHolder.text = (TextView)convertView.findViewById(R.id.card_text);
viewHolder.space = (TextView)convertView.findViewById(R.id.card_space);
viewHolder.pollSpace = (TextView)convertView.findViewById(R.id.poll_space);
viewHolder.type_icon = (ImageView)convertView.findViewById(R.id.card_icon);
viewHolder.answerView = (SurveyView)convertView.findViewById(R.id.poll_component);
viewHolder.rb = (RadioButton)viewHolder.answerView.findViewById(R.id.answer_voted_button);
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.type.setText(data.get(position).getType());
viewHolder.time.setText(data.get(position).getTime());
viewHolder.text.setText(data.get(position).getText());
viewHolder.answerView.setLayoutParams(params.get(position));
viewHolder.answerView.setLayout(context, "Multiple", 5, position);
viewHolder.answerView.setVisibility(false);
viewHolder.answerView.setAnswers(pollAnswers.get(position));
return convertView;
}
The fragment for the listview
SurveyListFragment extends ListFragment {
private ArrayList<Card> cardList;
private PollsAdapter adapter;
private ArrayList<Answer> answers;
ArrayList<Integer> visible;
private ArrayList<RelativeLayout.LayoutParams> params;
private ArrayList<Integer> pollAnswers;
/**
when user clicks on a poll display the poll options for it
*/
#Override
public void onListItemClick(ListView l, View view, final int position, long id) {
final PollsAdapter.ViewHolder holder = (PollsAdapter.ViewHolder)adapter.getView(position, view, l).getTag();
if (holder.getAnswerView().getHeight() == 0) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW, R.id.poll_space);
params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
//holder.getAnswerView().setLayoutParams(params);
this.params.set(position, params);
for (int i = 0; i < holder.getAnswerView().getOptions().size(); i++) {
holder.getAnswerView().getOptions().get(i).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int p = 0; p < holder.getAnswerView().getOptions().size(); p++) {
if (holder.getAnswerView().getOptions().get(p) == v) {
holder.getAnswerView().setAnswers(p);
pollAnswers.set(position, p);
adapter = new PollsAdapter(getActivity(), cardList, SurveyListFragment.this.params, pollAnswers);
setListAdapter(adapter);
}
}
}
});
}
}
else {
holder.getAnswerView().setVisibility(false);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 0);
params.addRule(RelativeLayout.BELOW, R.id.poll_space);
params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
this.params.set(position, params);
// holder.getAnswerView().setLayoutParams(params);
adapter.notifyDataSetChanged();
}
super.onListItemClick(l, view, position, id);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setListAdapter(adapter);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
cardList = new ArrayList<>();
answers = new ArrayList<>();
visible = new ArrayList<>();
params = new ArrayList<>();
pollAnswers = new ArrayList<>();
Answer answer = new Answer();
answer.setText("one");
answers.add(answer);
answer = new Answer();
answer.setText("two");
answers.add(answer);
answer = new Answer();
answer.setText("three");
answers.add(answer);
answer = new Answer();
answer.setText("four");
answers.add(answer);
Card card = new Card();
card.setType("Polls");
card.setText("What issue listed below would you like to see as a priority for Nashville’s next mayor?");
card.setTime("Closing Soon");
for (int i = 0; i < cardList.size(); i++) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 0);
params.addRule(RelativeLayout.BELOW, R.id.poll_space);
params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
this.params.add(params);
pollAnswers.add(-1);
}
adapter = new PollsAdapter(getActivity(), cardList, params, pollAnswers);
}

Parse the survey object to the view class when you create the convertView. And parse a new object every time recycle previous views. Here are some codes.
1) Initialize the views in ProductListItemView
public ProductListItemView(Context context, ProductItem item) {
super(context);
mProductItem = item;
initView(context);
}
/**
* This function sets up all the Views contained in the FrameLayout
*
* #param context
*/
private void initView(Context context) {
addView(LayoutInflater.from(context).inflate(R.layout.list_item_product, null));
ButterKnife.inject(this);
if (mProductItem != null) {
setProductItem(mProductItem);
}
}
2) set object to the view
public void setProductItem(final ProductItem item) {
/**
* Clear Listener. Important!! Cause by Android Recycle View
* Do whatever you want to reset the recycled view or new view
*/
mPurchase.setOnClickListener(null);
endorsed_by_image.setVisibility(INVISIBLE);
endorsed_by_name.setVisibility(INVISIBLE);
mBtnEndorse.setOnCheckedChangeListener(null);
mProductItem = item;
mProductName.setText(mProductItem.getName());
3) In your adapter
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ProductItem item = mProducts.get(position);
if (convertView == null) {
convertView = new ProductListItemView(getActivity(), item);
} else {
((ProductListItemView) convertView).setProductItem(item);
}
}
Hope I explain it well.
And in getView(), it is better to implement ViewHolder. Visit http://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html

Related

Listview add item one at a time

I have a listview and a button in my main activity and three layout ressource files (right.xml, mid.xml and left.xml [They're relative layout]).
I want to make an arrayList (with strings and drawable (images)) and each time I push the button in main.xml the first content of the arrayList will appear at the bottom of the screen (either left, mid or right --> depend of the order of the arrayList) and when I click again the next item (string or drawable) will appear beneath it, pushing it in an upward motion.
UPDATE
I made a Model and an Adapter
Here is the model
public class ModelC1 {
public String C1Name;
public String C1Text;
public int id;
public boolean isSend;
public ModelC1(String C1Name, String C1Text, int id, boolean isSend){
this.id = id;
this.C1Name = C1Name;
this.C1Text = C1Text;
this.isSend = isSend;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public String getC1Name() {
return C1Name;
}
public void setC1Name(String C1Name){
this.C1Name = C1Name;
}
public String getC1Text() {
return C1Text;
}
public void setC1Text (String C1Text){
this.C1Text = C1Text ;
}
public boolean isSend() {
return isSend;
}
public void setIsSend(boolean send){
isSend = send;
}
Here is the Adapter
public class AdapterC1 extends BaseAdapter {
private List<ModelC1> listChat;
private LayoutInflater inflater;
private Context context;
public AdapterC1(List<ModelC1> listChat, Context context){
this.listChat = listChat;
this.context = context;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return listChat.size();
}
#Override
public Object getItem(int i) {
return listChat.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
View vi = convertView;
if(convertView == null ){
if(listChat.get(i).isSend() == 0)
vi=inflater.inflate(R.layout.list_send,null);
else if ((listChat.get(i).isSend() == 1))
vi=inflater.inflate(R.layout.list_recv,null);
else if ((listChat.get(i).isSend() == 2))
vi=inflater.inflate(R.layout.list_mid,null);
}else{
if(listChat.get(i).isSend() == 0)
vi=inflater.inflate(R.layout.list_send,null);
else if ((listChat.get(i).isSend() == 1))
vi=inflater.inflate(R.layout.list_recv,null);
else if ((listChat.get(i).isSend() == 2))
vi=inflater.inflate(R.layout.list_mid,null);
}
if(listChat.get(i).isSend() !=0 || listChat.get(i).isSend() !=1 || listChat.get(i).isSend() !=2 ){
BubbleTextView bubbleTextView = (BubbleTextView) vi.findViewById(R.id.bubbleChat);
if(bubbleTextView != null)
bubbleTextView.setText(listChat.get(i).C1Text);
TextView nameTextView = (TextView) vi.findViewById(R.id.nameChat);
if(nameTextView != null)
nameTextView.setText(listChat.get(i).C1Name);
}else{
vi=inflater.inflate(R.layout.list_mid,null);
BubbleTextView bubbleTextView = (BubbleTextView) vi.findViewById(R.id.bubbleChat);
bubbleTextView.setText("THE END");
}
return vi;
}
And here is the activity
public class Chat1 extends AppCompatActivity {
private static final String TAG = "Chat1";
private AdapterC1 adapter;
private List<ModelC1> listChat = new ArrayList<>();
private int count = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat1);
RecyclerView chatContent1 = findViewById(R.id.chatContent1);
}
private ModelC1 setUpMessage(){
Log.d(TAG, "setUpMessage: Exec");
return();
}
///OnClick of the button in the activity_chat1.xml
public void nextClicked1(View view) {
Log.d(TAG, "nextClicked: Is Clicked");
///After the limit of the arraylist is reached
final int limit = 40;
if(count == limit){
Log.d(TAG, "nextClicked: Limit Reached");
Intent i = new Intent(Chat1.this, MainActivity.class);
startActivity(i);
}else{
///Call the list
loadList(null);
}
}
///Load the list of arrays?
public void loadList(View view){
ModelC1 chat = setUpMessage();
listChat.add(chat);
///The ID of the recycleview in the activity_chat1.xml
final RecyclerView recyclerview = findViewById(R.id.chatContent1);
///The adapter
final AdapterC1 adapter = new AdapterC1(listChat, this);
///Make the recyclerview always scroll
///the adapter
///recyclerview.setAdapter(adapter);
}
My questions are now how do I make the ArrayList (containing strings and drawables) and how to link the ArrayList to make it appear one by one when I click on the button ?
As for the ArrayList, will soemthing like that works ?
private List<List<String>> textChat1 = new ArrayList<List<String>>();
ArrayList<String> textChat1 = new ArrayList<String>();
textChat1.add("This is message 1");
textChat1.add("This is message 2");
textChat1.add("This is message 2");
addresses.add(textChat1);
How can I add images and how to say which strings inflate which layout (left, mid or right) ?
You can do your job like this: in your Adapter's getView method ,
#Override
public View getView(int position, View convertView, ViewGroup container) {
if (convertView == null) {
if (position == 1) {
convertView = getLayoutInflater().inflate(R.layout.left, container, false);
} else if (position == 2) {
convertView = getLayoutInflater().inflate(R.layout.mid, container, false);
} else {
convertView = getLayoutInflater().inflate(R.layout.right, container, false);
}
}
//your code here
return convertView;
}
This will do your job, but, I suggest you to use Recyclerview because it's more efficient and better in terms of looks as well as memory management.

Custom adapter returning wrong row Textview Text

I am implementing a custom adapter for listview. In which i have some textview and one checkbox.for checkbox i have implemented setOnCheckedChangeListener.But the problem is when i check a checkbox i am trying to get that row textview text. but it returning last row textview text.
Code
public class CustomStoreAdapter extends BaseAdapter implements Filterable {
ItemFilter mFilter;
int price;
private int lastPosition = -1;
ViewHolder mHolder;
ArrayList<String> favHotel;
private static SparseBooleanArray positionArray=new SparseBooleanArray();
SharedPreferences sharedPreferences;
public static ArrayList<HashMap<String,String>> finalHashList;
public static ArrayList<HashMap<String,String>> tempName;
public static ArrayList<Integer> selectedIds = new ArrayList<Integer>();
Context context;
String flag;
String favId;
ArrayList<String> htlId;
String [] favArr;
public CustomStoreAdapter(String flag, Context context, ArrayList<HashMap<String, String>> finalHashList, String favId) {
System.out.println("custom size>>"+finalHashList.size());
this.context = context;
CustomStoreAdapter.finalHashList =finalHashList;
for (int i=0;i<finalHashList.size();i++) {
htlId.add(finalHashList.get(i).get("id"));
}
tempName=finalHashList;
selectedIds=new ArrayList<>();
this.flag=flag;
this.favId=favId;
if (!favId.equals(""))
{
favId=favId.substring(6,favId.length());
//Log.e("substring favId",favId);
favArr=favId.split(",");
}
Log.e("flag is>>>",flag);
}
#Override
public int getCount() {
return finalHashList.size();
}
#Override
public Object getItem(int position) {
return finalHashList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public static void append( ArrayList<HashMap<String, String>> finalHashList1) {
}
public static StringBuilder getCheckedItems() {
StringBuilder mTempArry = new StringBuilder();
mTempArry.append("htlid=");
for(int i=0;i<finalHashList.size();i++) {
if(positionArray.get(i)) {
mTempArry.append(finalHashList.get(i).get("id"));
mTempArry.append(",");
}
}
return mTempArry;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
favHotel=new ArrayList<>();
View v = convertView;
sharedPreferences = context.getSharedPreferences("hotelDekho", Context.MODE_PRIVATE);
if(finalHashList.size() > position) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TypefaceUtil.overrideFont(context.getApplicationContext(), "SERIF", "fonts/splash-font.ttf");
if (v == null) {
v = inflater.inflate(R.layout.serch_result_page, parent, false);
mHolder = new ViewHolder();
mHolder.txtId=(TextView)v.findViewById(R.id.txtId);
mHolder.txthotelRating = (TextView) v.findViewById(R.id.txtRating);
mHolder.txthotelName = (TextView)v.findViewById(R.id.Hotel_name);
mHolder.txtFavorite=(CheckBox) v.findViewById(R.id.imgFavorite);
mHolder.txthotelLocation = (TextView) v.findViewById(R.id.Hotel_location);
mHolder.txthotelPrice = (TextView) v.findViewById(R.id.price);
mHolder.txthotelPrice2 = (TextView) v.findViewById(R.id.price2);
mHolder.txthotelIconPlace = (TextView)v.findViewById(R.id.locIcon);
mHolder.txtLock = (TextView)v.findViewById(R.id.txtLock);
mHolder.txthotelIconR1 = (TextView) v.findViewById(R.id.txtR1);
mHolder.txthotelIconR2 = (TextView) v.findViewById(R.id.txtR2);
mHolder.rhotelRating = (CustomRatingBar) v.findViewById(R.id.ratingBar1);
mHolder.lnrPrice=(LinearLayout)v.findViewById(R.id.lnrPrice);
mHolder.imgHotel = (ImageView) v.findViewById(R.id.hotel_image);
mHolder.lnrRating=(LinearLayout)v.findViewById(R.id.lnrRating);
mHolder.lnrSignHotelList=(LinearLayout)v.findViewById(R.id.lnrSignHotelList);
mHolder.txthotelIconPlace.setTypeface(FontManager.getTypeface(context, FontManager.FONTAWESOME));
mHolder.txthotelIconR1.setTypeface(FontManager.getTypeface(context, FontManager.FONTAWESOME));
mHolder. txthotelIconR2.setTypeface(FontManager.getTypeface(context, FontManager.FONTAWESOME));
mHolder.txtLock.setTypeface(FontManager.getTypeface(context, FontManager.FONTAWESOME));
mHolder.txtFavorite.setTag(position);
v.setTag(mHolder);
}else
{
mHolder = (ViewHolder) v.getTag();
mHolder.txtFavorite.setOnCheckedChangeListener(null);
}
Animation animation = AnimationUtils.loadAnimation(context, (position > lastPosition) ? R.anim.up_from_bottom : R.anim.down_from_top);
v.startAnimation(animation);
lastPosition = position;
mHolder.txtId.setText(finalHashList.get(position).get("id"));
mHolder.txthotelName.setText(finalHashList.get(position).get("name"));
mHolder.txthotelLocation.setText(finalHashList.get(position).get("location"));
mHolder.txthotelRating.setText(finalHashList.get(position).get("rating") + "/5");
// mHolder.txtFavorite.setChecked(positionArray.get(position));
mHolder.txtFavorite.setChecked(positionArray.get(position));
for (int i=0;i<favArr.length;i++)
{
if(favArr[i].equals(finalHashList.get(position).get("id")))
{
mHolder.txtFavorite.setChecked(true);
}
}
mHolder.txtFavorite.setOnCheckedChangeListener(mCheckedChangeListener);
if (!flag.equals("favHtl")) {
mHolder.lnrPrice.setVisibility(View.VISIBLE);
Float price1 = Float.parseFloat(finalHashList.get(position).get("price"));
mHolder.txthotelPrice2.setText(String.valueOf(Math.round(price1)));
if (SearchHotelResults.flag.equals("offer")) {
price = Math.round(price1 + price1);
} else
price = Math.round(price1 + ((price1 * 20) / 100));
mHolder.txthotelPrice.setText(String.valueOf(price));
mHolder.txthotelPrice.setPaintFlags(mHolder.txthotelPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
mHolder.rhotelRating.refreshDrawableState();
if (!sharedPreferences.getString("email","").equals(""))
{
mHolder.lnrSignHotelList.setVisibility(View.GONE);
}
mHolder.rhotelRating.setScore(Float.parseFloat(finalHashList.get(position).get("star")));
if (finalHashList.get(position).get("img").startsWith("hoteldekho")) {
loadImagePicaso( mHolder.imgHotel, Config.storeImagePath + finalHashList.get(position).get("img"));
} else {
loadImagePicaso( mHolder.imgHotel, finalHashList.get(position).get("img"));
}
}
return v;
}
CompoundButton.OnCheckedChangeListener mCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
Animation zoomOutAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.bounce);
buttonView.startAnimation(zoomOutAnimation);
positionArray.put(htlId.indexOf(mHolder.txtFavorite.getText().toString()), isChecked);
Log.e("array is>>",getCheckedItems().toString()+">>>>"+ finalHashList.indexOf(mHolder.txtId.getText().toString()));
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("favHotelId", getCheckedItems().toString());
editor.apply();
}
};
private class ViewHolder {
private TextView txtId;
private TextView txthotelRating;
private TextView txthotelName;
private TextView txthotelLocation;
private TextView txthotelPrice;
private TextView txthotelPrice2;
private TextView txthotelIconPlace;
private TextView txtLock;
private CheckBox txtFavorite;
LinearLayout lnrPrice;
private TextView txthotelIconR1;
private TextView txthotelIconR2;
private TextView txthotelIconArrow;
private CustomRatingBar rhotelRating;
private ImageView imgHotel;
private Button btnSubmit;
private LinearLayout lnrRating;
private LinearLayout lnrSignHotelList;
}
}
Please help me to how to get same row textview text on checkbox click
Problem:
Currently you're storing your ViewHolder in a class level field, which is being set in getView(), its going to be set to the latest ViewHolder every time ListView is calling getView() and there's absolutely no guarantee in the order of the position the getView() is called for. Its going to get random ViewHolder references, creating problems for you to track position So a class level ViewHolder isn't good solution.
Solution:
You need to keep track of position related to every check box. Tag the position to checkbox and get it in the listener as follow:
mHolder.txtFavorite.setOnCheckedChangeListener(mCheckedChangeListener);
mHolder.txtFavorite.setTag(position+""); //tag position as String object
Now you can get this position in your listener:
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//Since we set position in form of String, we need to convert String to int
int position = Integer.parseInt(buttonView.getTag());
}
You save position of mHolder.txtFavorite to tag, so you should just read the right position from tag, not from text
positionArray.put(htlId.indexOf(mHolder.txtFavorite.getTag()), isChecked);

How to avoid duplicate data in recyclarview when scrolling recycler view

We are using recyclarview for first time. My problem is when scrolling recyclar duplicate data is adding to view. In Below Code:
public class ProductOptions_RecyclerAdapter extends RecyclerView.Adapter<ProductOptions_ListRowHolder> {
private ArrayList<Product_Details> storeItemList;
HashMap<String, List<Product_Details>> product_items = new HashMap<String, List<Product_Details>>();
private Context mContext;
List<String> arrlist_skuitemName = new ArrayList<String>();
List<String> arrlist_skuitemLabel = new ArrayList<String>();
public ProductOptions_RecyclerAdapter(Context context, List<String> arrlist_skuitemName, List<String> arrlist_skuitemLabel, HashMap<String, List<Product_Details>> product_items) {
this.product_items = product_items;
this.mContext = context;
this.arrlist_skuitemName = arrlist_skuitemName;
this.arrlist_skuitemLabel = arrlist_skuitemLabel;
}
#Override
public ProductOptions_ListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_productoptions, null);
ProductOptions_ListRowHolder store = new ProductOptions_ListRowHolder(v);
return store;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onBindViewHolder(ProductOptions_ListRowHolder holder, int position) {
holder.name.setText(Html.fromHtml(arrlist_skuitemName.get(position)));
holder.label.setText(Html.fromHtml(arrlist_skuitemLabel.get(position)));
List<Product_Details> items = product_items.get(arrlist_skuitemName.get(position));
Log.d("listdata","min postion"+position+" / "+items.size());
for (int i = 0; i < items.size(); i++) {
RadioButton[] rb = new RadioButton[items.size()];
Product_Details pd = items.get(i);
rb[i] = new RadioButton(mContext);
rb[i].setTextColor(ColorStateList.valueOf(Color.parseColor("#000000")));
rb[i].setButtonTintList(ColorStateList.valueOf(Color.parseColor("#ff9900")));
holder.rd_option.addView(rb[i]);
rb[i].setText(pd.getName());
TextView tv = new TextView(mContext);
LinearLayout.LayoutParams buttonParams1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
buttonParams1.gravity = Gravity.END;
tv.setLayoutParams(buttonParams1);
tv.setText(pd.getSalePrice());
tv.setTextSize(15);
// tv.setGravity(Gravity.RIGHT| Gravity.END);
//holder.ll_priceitem.addView(tv);
holder.rd_option.addView(tv);
}
holder.rd_option.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
int radioButtonID = group.getCheckedRadioButtonId();
RadioButton radioButton = (RadioButton) group.findViewById(radioButtonID);
Toast.makeText(mContext,radioButton.getText(),Toast.LENGTH_LONG).show();
}
});
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
ProductOptions_ListRowHolder tt = (ProductOptions_ListRowHolder) v.getTag();
int pos = tt.getPosition();
}
};
//Handle click event on both title and image click
holder.rd_option.setOnClickListener(clickListener);
holder.rd_option.setTag(holder);
// notifyDataSetChanged();
}
#Override
public int getItemCount() {
return (null != product_items ? product_items.size() : 0);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
In this Product_Details is a model class.Here we are trying to add radiobuttons dynamically based on service response i.e, added to HashMap(product_items).
When we are scrolling recyclar view automatic duplicates are adding.
For activity created data is correct.when scrolling duplicates adding.
Please Guide us, where we are going wrong?
Thanks in Advance.

ListView does not render all items until interacted with

I have a very strange problem while using my ListView.
Only a part of my adapter items are renderd in the listview on screen but when I interact with the listview (ie tries to scroll it) all items are renderd properly.
This fenonemon only occurs if i have less items than the screen can show. Take a look at these screenshots below.
Before interaction:
After interaction:
Source code of activity where adding items:
String[] jRests = getResources().getStringArray(R.array.j_restaurants);
String[] lRests = getResources().getStringArray(R.array.l_restaurants);
items = new ArrayList<Object>();
items.add(getString(R.string.campus_j));
for(String item : jRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
items.add(getString(R.string.campus_l));
for(String item : lRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
adapter = new BaseSectionAdapter(this, R.layout.list_item_fragment_header);
if(!isTabletView()){
adapter.setSelectedItem(-1);
}
adapter.setItems(items);
Code of adapter:
public class BaseSectionAdapter extends AmazingAdapter {
private LayoutInflater inflater;
private int selectedItem = 0;
private List<Object> items;
private List<SectionItem> sections = new ArrayList<SectionItem>(10);
private List<Class> itemTypes = new ArrayList<Class>();
private List<Integer> sectionPositions = new ArrayList<Integer>();
private int listHeaderLayoutId;
private View headerView;
public static interface ISectionListItem {
public void setProps(View convertView, int position, int selectedItem);
public View getLayout(LayoutInflater inflater);
}
private class SectionItem implements Serializable {
private static final long serialVersionUID = -8930010937740160935L;
String text;
int position;
public SectionItem(String text, int position) {
this.text = text;
this.position = position;
}
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId, List<Object> listItems) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
initListItems(listItems);
}
private void init(Context context) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setSelectedItem(int position) {
selectedItem = position;
}
// public List<ListItem> getItems() {
// return items;
// }
private void initListItems(List<Object> itemList) {
int curSection = -1;
//int curPosition = 0;
//curSection = 0;
this.items = itemList;
itemTypes.clear();
sections.clear();
sectionPositions.clear();
int listSize = itemList.size();
for(int i = 0; i < listSize; i++){
Object currentItem = items.get(i);
if(currentItem instanceof String){
sections.add(new SectionItem((String) currentItem,i));
curSection++;
}
if(!itemTypes.contains(currentItem.getClass())){
itemTypes.add(currentItem.getClass());
}
sectionPositions.add(curSection);
}
Log.d("test", "No of items = "+items.size());
Log.d("test", "No of itemtypes = "+itemTypes.size());
Log.d("test", "View type count = "+getViewTypeCount());
}
public void setItems(List<Object> itemList) {
initListItems(itemList);
}
public int getCount() {
return items==null?0:items.size();
}
#Override
public int getViewTypeCount(){
return (itemTypes.size() == 0)?1:itemTypes.size();
}
#Override
public int getItemViewType(int position){
return itemTypes.indexOf(items.get(position).getClass());
}
#Override
public boolean isEnabled(int position){
return !(items.get(position) instanceof String || items.get(position) instanceof EmptySectionListItem);
}
#Override
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
#Override
protected void onNextPageRequested(int page) {
// TODO Auto-generated method stub
}
#Override
protected void bindSectionHeader(View view, int position,
boolean displaySectionHeader) {
// TextView lSectionTitle = (TextView) view
// .findViewById(R.id.txt_list_header);
// if (displaySectionHeader) {
// lSectionTitle.setVisibility(View.VISIBLE);
// lSectionTitle
// .setText(getSections()[getSectionForPosition(position)]);
// } else {
// lSectionTitle.setVisibility(View.GONE);
// }
}
#Override
public View getAmazingView(int position, View convertView, ViewGroup parent) {
Object curItemObject = items.get(position);
boolean isHeader = (curItemObject instanceof String);
if(convertView == null){
if(isHeader && headerView != null){
convertView = headerView;
}else if(isHeader){
convertView = inflater.inflate(listHeaderLayoutId, null);
headerView = convertView;
}else{
convertView = ((ISectionListItem) curItemObject).getLayout(inflater);
}
}
if(isHeader){
TextView header = ((TextView)convertView.findViewById(R.id.txt_list_header));
header.setText((String)curItemObject);
}else{
((ISectionListItem)curItemObject).setProps(convertView, position, selectedItem);
}
return convertView;
}
#Override
public void configurePinnedHeader(View header, int position, int alpha) {
TextView textView = ((TextView)header.findViewById(R.id.txt_list_header));
textView.setText(getSections()[getSectionForPosition(position)]);
}
#Override
public int getPositionForSection(int section) {
if(section >= sections.size()){
return 0;
}
return sections.get(section).position;
}
#Override
public int getSectionForPosition(int position) {
return sectionPositions.get(position);
}
#Override
public String[] getSections() {
String[] res = new String[sections.size()];
for (int i = 0; i < res.length; i++) {
res[i] = sections.get(i).text;
}
return res;
}
}
Code of layout:
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
FrameLayout listLayout = new FrameLayout(this);
LinearLayout.LayoutParams listParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
listParams.weight = 1;
listLayout.setId(LIST_FRAGMENT_VIEW_ID);
FrameLayout detailLayout = new FrameLayout(this);
LinearLayout.LayoutParams detailParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
detailParams.weight = 2;
detailLayout.setId(DETAIL_FRAGMENT_VIEW_ID);
layout.addView(listLayout, listParams);
layout.addView(detailLayout, detailParams);
if(savedInstanceState == null){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(listLayout.getId(), (Fragment) listFragment, TWO_PANEL_LIST_FRAGMENT_TAG);
ft.add(detailLayout.getId(), detailFragment);
ft.commit();
}
setContentView(layout);
try calling notifyDataSetChanged() in runOnUIThread() method like I have shown below and it will work like a charm. :)
runOnUiThread(new Runnable() {
#Override
public void run() {
messageAdapter.notifyDataSetChanged();
}
});
i dont know what causes the problem, but if you don't find a logical solution to it you could try something like this:
trigger an onTouchEvent() programmatically whenever you launch the ListView.
scroll down and back up programmatically as soon as the ListView is launched.
etc..
Add ListView widget to layout.xml and add content of list to that. Do not use FrameLayout as it probably is the cause of the problem. It is updating content after touch so the Layout it is on is no implementing the correct onCreate() setup as the ListView widget has.
Are you calling the method notifyDataSetChanged() on your adapter after adding new items? This causes the listview to refresh its view when the underlying dataset is changed.
If it still doesn't work, try notifyDataSetInvalidated() that causes the listview to redraw completely.
Solved it!!!
Problem was with the adapter trying to reuse the same section item. Not good!!!
Changed it to inflate the section item each time we hit a section!

How to display the textviews dynamically in a list view in android?

I am working on quiz application. It contains 2 types of tests. The first test contains questions with 3 options fixed. *The second test contains questions with options not fixed. i.e the options may be 4 or 5 or 6 based on the question.*
After the test I need to display the review page. Here is the review page code for the first type of test with fixed options.(Review page should contain the questions displayed for the test at that time)
My Code:
Review.java
public class Review extends Activity {
static ArrayList selectedoptionids = Test1.listarray;
static ArrayList<ArrayList<String>> questionslist = Test2.stringList1;
static ArrayList<ArrayList<String>> alloptionlist = Test2.optionstablelist;
static ArrayList<ArrayList<String>> all = new ArrayList<ArrayList<String>>();
ListView list;
Button next;
String op1, op2, op3, op4, op5;
ArrayList<String> arr1;
ArrayList<String> arr2;
int a, i;
static int k = 0;
static int p = 1;
static List<mainlist> entirelist = new ArrayList<mainlist>();
String quest;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.review);
list = (ListView) findViewById(R.id.listlist);
View header = getLayoutInflater().inflate(
R.layout.listview_header_text, null);
list.addHeaderView(header, null, false);
View footerView = getLayoutInflater().inflate(
R.layout.listview_footer_text, null);
list.addFooterView(footerView, null, false);
next = (Button) findViewById(R.id.next);
eachquestion();
lvAdapter adapter = new lvAdapter(this, entirelist) {
public boolean areAllItemsEnabled() {
return false;
}
public boolean isEnabled(int position) {
return false;
}
};
list.setAdapter(adapter);
}
public void eachquestion() {
arr1 = new ArrayList<String>();
for (i = p - 1; i < p + 3; i++) {
arr1 = questionslist.get(i);
arr2 = new ArrayList<String>();
for (int j = 0; j < 5; j++) {
arr2 = alloptionlist.get(0);
if (j == 0)
op1 = arr2.get(2);
else if (j == 1)
op2 = arr2.get(2);
else if (j == 2)
op3 = arr2.get(2);
}
}
entirelist.add(new mainlist(quest, op1, op2, op3));
}
}
}
mainlist.java
public class mainlist {
String question,option1,option2,option3;
public mainlist(String question,String option1,String option2,String option3) {
super();
this.question = question;
this.option1 = option1;
this.option2= option2;
this.option3 = option3;
}
public String getquestion() {
return question;
}
public void setquestion(String question) {
this.question = question;
}
public String getoption1() {
return option1;
}
public void setoption1(String option1) {
this.option1 = option1;
}
public String getoption2() {
return option2;
}
public void setoption2(String option2) {
this.option2 = option2;
}
public String getoption3() {
return option3;
}
public void setoption3(String option3) {
this.option3 = option3;
}
}
lvAdapter.java
public class lvAdapter extends BaseAdapter implements OnClickListener {
private Context context;
List<mainlist> list11 = Review.entirelist;
public lvAdapter(Context context, List<mainlist> list11 ) {
this.context = context;
this.list11 = list11 ;
}
public int getCount() {
return list11.size();
}
public Object getItem(int position) {
return list11.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
mainlist inst = list11.get(position);
if (convertView == null)
{
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.reviewrow, null);
}
TextView question = (TextView) convertView.findViewById(R.id.textView2);
tvPhone.setText(inst.getquestion());
TextView option1 = (TextView) convertView.findViewById(R.id.op1);
option1.setText(inst.getoption1());
TextView option2 = (TextView) convertView.findViewById(R.id.op2);
option2.setText(inst.getoption2());
TextView option3 = (TextView) convertView.findViewById(R.id.op3);
option3.setText(inst.getoption3());
return convertView;
}
#Override
public void onClick(View v) {
}
}
Now my problem is for the first test as we know the number of options are 3 so I have written the setter and getter methods for 1 question and 3 options and it is working fine. But for the second type of test how can I write the mainlist.java class for generating the setter and getter methods for unknown number of options.
Please help me regarding this...I am struggling for this since 3 days....
Thanks in advance...
Ok what you will need is to make a class named Quiz something like this:
public class Quiz
{
private String question;
private ArrayList<String> options; // no need to get separate variable for every option
public Quiz(String q, ArrayList<String> o)
{
super(); this.question = q; this.options = o;
}
//setter and getter.. like setOptions() getOptions() setQuestion() etc.. :/
}
now in make your entirelist a Quiz List like this:
List<Quiz> entirelist = new ArrayList<Quiz>();
and now pass single quiz + options to entirelist like this:
ArrayList<String> options = new ArrayList<String>();
options.add(op1);
options.add(op2);
options.add(op3);
entirelist.add(new Quiz(quest,options));
now in adapter's getView(), remove all options' TextViews and add them dnamically something like this:
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (convertView == null)
{
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.reviewrow, null);
}
Quiz currentQuiz = list11.get(position);
TextView question = (TextView) convertView.findViewById(R.id.textView2);
tvPhone.setText(currentQuiz.getquestion());
// now add options dynamically..
ArrayList<String> options = currentQuiz.getOptions();
for(String option : options)
{
TextView optionTextView = new TextView(context);
optionTextView.setText(option);
convertView.add(optionTextView);
}
return convertView;
}
Don't use XML.
Add the Views to the layout programatically, in Java. Then you can pick up the appropriate number of options dynamically.
(Almost) Everything in Android that you can do in XML, you can do in Java code.

Categories

Resources