Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am a beginner and I have seen many tutorials on how to create a list using RecyclerView, but I can't find any how to use a list without recycling. I have a list of 3 items. what type of view should I use if I don't want to recycle?
Another way to look at you list would be as simple items (since there are only 3). You can just add items to a LinearLayout with orientation as vertical.
You can even go further and create a common item layout XML, and using a for loop, inflate your LinearLayout. Example:
//create item class
#AllArgsConstructor #Getter
private static class Item {
private int iconId;
private String mainText;
private String detailsText;
}
// create item
private Item ITEM_1 = new Item(R.drawable.some_drawable, getString(R.string.some_string), getString(R.string.some_string));
//add item to an arrayList (only add what you want that logged in user to see :D)
itemList.add((ITEM_1))
//layout you want to add to
#BindView(R.id.content) LinearLayout layoutToAddTo;
LayoutInflater inflater = LayoutInflater.from(getContext());
for (Item item : itemList) { // a list which holds all your Items
//XML that the Item class matches.
View card = inflater.inflate(R.layout.card, layoutToAddTo, false);
bindContent(card, item);
card.setOnClickListener(__ -> /* set your listener */));
layoutToAddTo.addView(card);
}
//bind your content
private void bindContent(View view, Item item) {
((ImageView) view.findViewById(R.id.card_icon)).setImageDrawable(ContextCompat.getDrawable(context, item.getIconId());
((TextView) view.findViewById(R.id.card_main_text)).setText(item.getMainText());
((TextView) view.findViewById(R.id.card_details_text)).setText(item.getDetailsText());
}
Best for few items, otherwise try to use Recycler View.
You can use ListView if you don't want to recycle the list item.
Here ListView
Related
I have a recyclerView that each item of it contain a question title and also a recyclerView inside it. I want to change the color of items inside the second recyclerView when clicking on a send button. I do this with these lines of code:
(questionListView is the RecyclerView and ansRecycle is second RecyclerView)
for (int i=0;i<adapter.getItemCount();i++){
questionListView.scrollToPosition(i);
questionListView.
adapter.notifyItemChanged(i);
View view=questionListView.findViewHolderForAdapterPosition(i).itemView;
RecyclerView ansRecycle=view.findViewById(R.id.checkedAnswerLayout);
for(int j=0;j<ansRecycle.getAdapter().getItemCount();j++) {
View temp=ansRecycle.getChildAt(j);
CheckBox ch=temp.findViewById(R.id.checkedChoice);
if(ch.getText().toString().equals(questions.get(i).getCorrectAnswers())){
ch.setTextColor(Color.RED);
}
}
}
For items that are shown on screen all things are fine but for others, there is no existence ViewHolder and I can not change the color of them.
How can I do this?
The problem is that items that are not on screen doesn't exist. The whole point of recyclerview is that it uses small amount of views, and recycle them when they leave the screen.
What you should do is do the same "if" when you bind the data.:
#Override
public void onBindViewHolder(MyDataViewHolder holder, int position) {
if(ch.getText().toString().equals(questions.get(i).getCorrectAnswers())){
ch.setTextColor(Color.RED);
}
}
Work around solution would be:
add a field to the Question - like int color = your color with setters/getters
on click get the questionItem and set the color of it to a new color
onBind of the recyclerView's find the textView and set the color based on your queston
same with answers.
for example
holder.textView.setColor(question.getColor());
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
enter image description here
i have already created gridview.i want to remove the images by a single click.
thank u.
Pretty simple,
Assuming that you are using recyclerview
class ViewHolder extends RecyclerView.ViewHolder {
View vCross;
ViewHolder(View itemView) {
vCross = itemView.findViewById(R.id.your_view_id) // Giving reference
vCross .setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Assuming dataset is your adapter dataset
dataSet.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());
}
});
}
}
Summary, In your ViewHolder, when user clicks on remove button - remove item from your adapter dataSet and notify adapter that, item has been removed at specific position.
In my QuestionsActivity, I am showing a question and bunch of answers. The question is displayed on TextView and answers are displayed on ListView that is composed of TextViews. There is an ActionButton named "Check Answer" and when it is clicked, it shows the correct answer by changing the background color of the TextView in the ListView.
The background changing code looks like this:
if (allAnswers.get(i).isCorrect())
{
mAnswerList.getChildAt(i).setBackgroundColor
(getResources().getColor(R.color.correct_answer_background));
return;
}
and now there are two Buttons at the footer section of this QuestionsActivity called PreviousQuestionButton and NextQuestionButton and they are basically navigation buttons between questions.
The problem is, when I go to the next question after clicking on "Check Answer" button, the answer background color doesn't go away and remains in the next question answer options. I tried invalidate(), refreshDrawableState() method of ListView but no luck!
This is the method which displays the answers for a given question:
private void showAnswers(int questionLocation)
{
int questionId = mAllQuestions.get(questionLocation).getQuestionId();
List<Answer> answers = mAnswerRepository.getAllByQuestionId(questionId);
mAnswerAdapter.clear();
for (int i = 0; i < answers.size(); i++)
{
mAnswerAdapter.add(mOptionLetters[i] + ". "
+ answers.get(i).getAnswerText());
}
mAnswerAdapter.notifyDataSetChanged();
}
My Question
What I want is that when I click on next or previous buttons, the background color of the correct answer in ListView should disappear so that next and previous question button can show non-selected answer options list to the user. Is there any method which resets ListView to a state which does not have any background applied?
For selected answer option, I am using mAnswerList.clearChoices() in order to unselect but it does not apply for correct answer background color.
Well, to reset the color you can very well hard-reset the adapter by creating a new one. So don't clear and add as that may keep the views in the state they were before. I am not too sure about this since I am not clearing or adding from an adapter, but always creating a new one to fulfill my new needs.
Anyway, another reason why things may not go in the direction you want is that the views may get recycled, since we're talking about a ListView. So if you want to highlight a list item, you should keep in the data model the information about highlight by initializing it to false and if the user selects one set the highlight state to true. I suppose the Answer class has as a minimum the following:
public class Answer {
private String data;
private boolean correct;
public String getData() {
return data;
}
public boolean isCorrect() {
return correct;
}
#Override
public String toString() {
return data;
}
}
So your adapter could look close to this - getView method is the most important to notice (don't forget to set to default background if the answer is incorrect or the adapter should not highlight correct answer):
public class MyAdapter extends ArrayAdapter<Answer> {
private boolean showCorrectAnswer;
private List<Answer> modelAnswers;
public MyAdapter(Context context, List<Answer> answers) {
super(context, android.R.layout.simple_list_item_1, answers);
this.modelAnswers = answers;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if(showCorrectAnswer && modelAnswers.get(position).isCorrect()) {
view.setBackgroundColor(getContext().getResources().getColor(R.color.correct_answer_background));
} else {
view.setBackgroundColor(getContext().getResources().getColor(R.color.default_background));
}
}
public void setShowCorrectAnswer(boolean showCorrectAnswer) {
this.showCorrectAnswer = showCorrectAnswer;
notifyDataSetChanged();
}
}
What you need to do is to keep a reference to this custom adapter and if you need to highlight the correct answer or not simply call setShowCorrectAnswer(true / false);. It will trigger a redraw and in the getView() it will decide what to do based on adapter state and correct answer.
Hope it make sense ... I wrote all this while drinking a beer :)
Basically, I agree with the answer from payeli - you should change the background of selected answer in the "next/previous question" button.
But then there is this question:
"Is there any method which resets ListView to a state which does not have any background applied?"
Answer to this (as far as I know) is: not directly. But there are two workarounds.
If you call notfiyDataSetChange, not all views are completely redrawn. If possible, just the appropriate values are changed. It's mainly for performance reasons. (Imagine having 1000 contacts with images and names dumped and redrawn)
So how can you deal with this? (Other then reseting the background in the onClick method) Since you said these items are answers for a question, I assume you are not concerned about performance because there won't be too many of them.
Then you can simply:
A) Create new instance of Adapter instead of changing data in the old one. When you switch adapters, all views in list are removed, so, no recycling can happen in the new adapter.
B) Create custom Adapter, override getView method and make sure every time view is requested, you return a new view, so no recycling can happen.
Again: this really isn't "performance friendly" and should not be used with big lists with a lot of items!
If you want to know more, feel free to ask in comments or read the reference of Adapter class, especially the parameter convertView of getView method. (http://developer.android.com/reference/android/widget/Adapter.html)
As per my understanding U need to change color of text view in one of the list view row i.e row containing correct answer.
If this is your problem then On Click of button simply clear list view and recreate list view. Not when list view is recreated then check out position of row which contains correct answer. After getting row position simply change color of text view.
For Ex: In your Adapter class check as fallows in your getView();
for ( int i = 0; i < position.length ; i++ )
{
if(position == your_required_position){
{
textview.setColor(Color.BLUE);
}else{
textview.setColor(Color.BLACK);
}
}
In the onClickListener of "Check Answer" button, you need to reset the color:
void onClick (View v){
..............
mAnswerList.getChildAt(currentQuestion).setBackgroundColor
(getResources().getColor(R.color.default_answer_background));
}
you can save the default background somewhere, and when you press next/previous question button you should apply that color. Example:
TypedArray array = getTheme().obtainStyledAttributes(new int[] {
android.R.attr.colorBackground,
android.R.attr.textColorPrimary,
});
int backgroundColor = array.getColor(0, 0xFF00FF);
int textColor = array.getColor(1, 0xFF00FF);
array.recycle();
I found this code online to get background and text color (you can just keep the background part), when the onClick activates just set the background of your view to "backgroundColor"
This question already has answers here:
Retaining position in ListView after calling notifyDataSetChanged
(7 answers)
Closed 7 years ago.
I have a listView and I want to add new items to the top of the list view but I dont want list view to scroll its content. I want user to look at the same item as he was looking before new items were added.
This is how I add new items to ListView:
this.commentsListViewAdapter.addRangeToTop(comments);
this.commentsListViewAdapter.notifyDataSetChanged();
and this is addRangeToTop method:
public void addRangeToTop(ArrayList<Comment> comments)
{
for (Comment comment : comments)
{
this.insert(comment, 0);
}
}
this is my listView:
<ListView
android:id="#+id/CommentsListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/AddCommentLayout"
android:stackFromBottom="true" >
</ListView>
What I want to do is to load old comments when user scrolls to the top.
Thank you for your help.
I have found solution here Retaining position in ListView after calling notifyDataSetChanged
Sorry for duplicate question.
The final code is this:
int index = this.commentsListView.getFirstVisiblePosition() + comments.size();
View v = this.commentsListView.getChildAt(commentsListView.getHeaderViewsCount());
int top = (v == null) ? 0 : v.getTop();
this.commentsListViewAdapter.AddRangeToTop(comments);
this.commentsListViewAdapter.notifyDataSetChanged();
this.commentsListView.setSelectionFromTop(index, top);
May be this is what you are looking for:
android:transcriptMode="normal"
"This makes list automatically scroll to the bottom when a data set change notification is received and only if the last item is already visible on screen." - as quoted here
Also have a look at ListView's method public void setSelection (int position). After you added new comments, and notified your adapter, you can use it to keep the current item selected.
// Get the current selected index
int previousSelectedIndex = yourListView.getSelectedItemPosition();
// Change your adapter
this.commentsListViewAdapter.AddRangeToTop(comments);
this.commentsListViewAdapter.notifyDataSetChanged();
// Determine how many elements you just inserted
int numberOfInsertedItems = comments.size();
// Update the selected position
yourListView.setSelection(previousSelectedIndex + numberOfInsertedItems);
NOTE: Code is untested. Good luck
This question already exists:
Closed 10 years ago.
Possible Duplicate:
Dynamic ListView with dynamic GUI
I have to fetch the data from sqlite database. Database will contain countryname , card name and card id and status, I have to display countryname then list of cards dynamically for example if USA has four card then in list view it will display USA then all then four cards then UK then cards of UK and so on it should be implemented with check box for each item and if user clicks on suppose a card which is displaying in USA category then I have to update its status in database for example if a card in USA is checked then in database we have to update "yes" similar function for other cards .. So how to achieve this?
I think you are asking about dynamic list view with check box in its list's cell.
First of all you need an adapter for filling your list...Like This..
ListView listView=(ListView)findViewById(R.id.listView);
listView.setAdapter(new MyListAdapter (<Your ArrayList>));
Now when ever we use check box or editbox in list.Then when we scroll list it call its getview method every time. So we need to manage value or status of components. Here to manage status of checkbox I had used Arraylist of boolean type.
Make an XMl file for your list's cell. Put listeners for list's cell components inside getview method.
public class MyListAdapter extends BaseAdapter
{
private ArrayList<HashMap<String, String>> data;
private ArrayList<Boolean> checks=new ArrayList<Boolean>();
public MyListAdapter ( ArrayList<HashMap<String, String>> d)
{
data=d;
inflater = (LayoutInflater)baseActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (int i = 0; i < d.size(); i++)
{
checks.add(i, false);//as first no check box is checked. So fill it with false value
}
}
public int getCount()
{
return data.size();
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_row, null);
name = (TextView)vi.findViewById(R.id.name);// name
checkBox=(CheckBox)vi.findViewById(R.id.check_box);
email_id = (TextView)vi.findViewById(R.id.e_mail_id); // email ID
mobile_no = (TextView)vi.findViewById(R.id.mobile_no); // mobile
checkBox.setTag(Integer.valueOf(position));
checkBox.setOnClickListener(this);
checkBox.setChecked(checks.get(position));
name.setText(<set name form any data source>);
email_id.setText(<set emailid form any data source>);
mobile_no.setText(<set mobile form any data source>);
return vi;
}
}
Hope this should help you.
Cheers...
So in your case you have to implement Multiselect Expandable listview..
Okay, so what you need first of all is to create an xml file for each row in your ListView to be inflated.
So you have some textview for your country name etc. But now to the tricky part to adding dynamically those "cards" depending on the amount:
In your xml for each row, add a LinearLayout where you want the specified cards to appear, and then in the getView() method inside the ArrayAdapter (the custom one you've created) you need to do something like this:
cardsLayout = (LinearLayout) v.findViewById(R.id.cards_layout);
cardsLayout.removeAllViews(); // rows are reused in listview, so this prevent them to be duplicated
ImageView image;
for(int i = 0; i < country.getCards(); i++){ // I assume you're using array for cards of each country
image = new ImageView(ActivityName.this);
layoutParams = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1.0f);
image.setLayoutParams(layoutParams);
image.setImageBitmap(someBitmapImage);
imageLayout.addView(image);
{
I assume you know how to create your own adapter. And this snippet of code just dynamically creates ImageViews and sets there weight to 1, so they will be equal in size through the row. If you need checkboxes or whatever, you can use the same approach by changing the ImageView to something else.