Reputation: 33
I want to loop through all CardViews and change the text and color of a TextView within a single CardView item using a button click. The following code seems to produce the desired results but I'm not certain that it's the most effective code or even accurate (index).
// CustomAdapter
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private Context context;
private List<MyModel> list;
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
holder.textName.setText(list.get(position).getName());
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
}
@Override
public int getItemCount() {
return list.size();
}
}
//CustomViewHolder
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView textName, textAge;
public CustomViewHolder(@NonNull View itemView) {
super(itemView);
textName = itemView.findViewById(R.id.textName);
textAge = itemView.findViewById(R.id.textAge);
}
}
MainActivity
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
List<MyModel> myModelList;
CustomAdapter customAdapter;
private Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadData();
}
private void loadData() {
recyclerView = findViewById(R.id.recycler_main);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
myModelList = new ArrayList<>();
myModelList.add(new MyModel("Joe", 21));
myModelList.add(new MyModel("Jane", 26));
myModelList.add(new MyModel("Kyle", 19));
myModelList.add(new MyModel("Scott", 30));
customAdapter = new CustomAdapter(this, myModelList);
recyclerView.setAdapter(customAdapter);
}
public void onClickBtn(View v)
{
String searchString = "Kyle";
for (int x = recyclerView.getChildCount(), i = 0; i < x; ++i) {
RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(recyclerView.getChildAt(i));
TextView txtName = holder.itemView.findViewById(R.id.textName);
if (txtName.getText().toString().equals(searchString.toString())) {
txtName.setText("Found " + txtName.getText().toString());
txtName.setTextColor(Color.GREEN);
customAdapter.notifyItemChanged(x);
}
}
}
}
//MyModel
public class MyModel {
String name = "";
int age = 0;
public MyModel(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
It's important that I iterate through the list in button click event. Functionality to be changed later. Really appreciate any advice and feedback. Update. Must be an index or other related problem. When my ArrayList contains many, many more items and button is clicked, a lot of non found rows text and color are changed.
Upvotes: 0
Views: 797
Reputation: 2904
Try this adapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private Context context;
private List<MyModel> list;
private String searchString = "";
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
if(list.get(position).getName().equals(searchString)){
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
} else {
holder.textName.setText(list.get(position).getName());
holder.textName.setTextColor(Color.BLACK);
}
}
@Override
public int getItemCount() {
return list.size();
}
public void setNewSearchString(String searchString) {
this.searchString = searchString;
notifyDataSetChanged();
}
}
and button click:
public void onClickBtn(View v)
{
customAdapter.setNewSearchString("Kyle");
}
For Multiple search, the adapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private Context context;
private List<MyModel> list;
//private String searchString = "";
private ArrayList<String> arraySearchStrings = new ArrayList<>();
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
boolean found = false;
for (String searchString : arraySearchStrings) {
if (list.get(position).getName().equals(searchString)) {
found = true;
break;
}
}
if (found) {
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
} else {
holder.textName.setText(list.get(position).getName());
holder.textName.setTextColor(Color.BLACK);
}
}
@Override
public int getItemCount() {
return list.size();
}
public void setNewSearchString(String searchString) {
//this.searchString = searchString;
arraySearchStrings.add(searchString);
notifyDataSetChanged();
}
public void resetSearchString() {
arraySearchStrings.clear();
notifyDataSetChanged();
}
}
Button click:
public void onClickBtn(View v)
{
customAdapter.setNewSearchString("Kyle");
customAdapter.setNewSearchString("Steve");
customAdapter.setNewSearchString("Joe");
}
Alternative answser:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
private Context context;
private List<MyModel> list;
private ArrayList<String> arraySearchStrings = new ArrayList<>();
private ArrayList<Boolean> arrayFound = new ArrayList<>();
private int[] arrayFoundCount;
private int foundTotalCount = 0;
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
arrayFoundCount = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
arrayFound.add(false);
arrayFoundCount[i] = 0;
}
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
holder.textCount.setText(String.valueOf(arrayFoundCount[position]));
if (arrayFound.get(position)) {
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
} else {
holder.textName.setText(list.get(position).getName());
holder.textName.setTextColor(Color.BLACK);
}
}
@Override
public int getItemCount() { return list.size(); }
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView textName, textAge, textCount;
public CustomViewHolder(@NonNull View itemView) {
super(itemView);
textName = itemView.findViewById(R.id.textName);
textAge = itemView.findViewById(R.id.textAge);
textCount = itemView.findViewById(R.id.textCount);
}
}
private int countFoundNameInList() {
int count = 0;
boolean found;
MyModel model;
arrayFound.clear();
for (int i = 0; i < list.size(); i++) {
model = list.get(i);
found = false;
for (String searchString : arraySearchStrings) {
if (model.getName().equals(searchString)) {
found = true;
arrayFoundCount[i] = arrayFoundCount[i]++;
count++;
break;
}
}
arrayFound.add(found);
}
return count;
}
public void setNewSearchString(String searchString) {
arraySearchStrings.add(searchString);
int newCount = countFoundNameInList();
if (newCount > foundTotalCount) {
Toast.makeText(context, searchString + " found.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Error: Nothing found!!", Toast.LENGTH_LONG).show();
}
foundTotalCount = newCount;
notifyDataSetChanged();
}
}
Upvotes: 1
Reputation:
I don't think this code will give you accurate result. you have to come up with different logic for this In your logic you are searching static name i am sure this is for demo purpose only. later you will implement with user input string. So As per my opinion you can create variable in your adapter that search mode is on or off after this when ever user start searching make searchMode On and same as when they done with searching set searchMode Off in your viewHolder Class you can update View on searchMode on off Status. You can Create 2 list 1 is for main List seconds is for searched list when user starts searching you have to filter main list with search string and then set it to searchedList and also make searchMode On and then update it to your adapter. rest will handle your adapter. no need to change it one by one from your list.
I am adding here required changes as per my opinion
Your Custom Adapter
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
private Context context;
private List<MyModel> list;
private Boolean isSearchModeOn = false;
public CustomAdapter(@NonNull Context context, @NonNull List<MyModel> list) {
this.context = context;
this.list = list;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
if (isSearchModeOn){
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
}else {
holder.textName.setText(list.get(position).getName());
//Also set Here normal text color
}
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
}
@SuppressLint("NotifyDataSetChanged")
public void updateList(@NonNull List<MyModel> searchedList){
list = searchedList;
notifyDataSetChanged();
}
@SuppressLint("NotifyDataSetChanged")
public void setSearchMode(@NonNull Boolean isOn){
isSearchModeOn = isOn;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return list.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
@NonNull
public TextView textName, textAge;
public CustomViewHolder(@NonNull View itemView) {
super(itemView);
textName = itemView.findViewById(R.id.textName);
textAge = itemView.findViewById(R.id.textAge);
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
List<MyModel> myModelList;
List<MyModel> searchedList;
CustomAdapter customAdapter;
@Override
protected void onCreate(@NonNull Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
loadData();
}
private void loadData() {
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
myModelList = new ArrayList<>();
myModelList.add(new MyModel("Joe", 21));
myModelList.add(new MyModel("Jane", 26));
myModelList.add(new MyModel("Kyle", 19));
myModelList.add(new MyModel("Scott", 30));
customAdapter = new CustomAdapter(this, myModelList);
recyclerView.setAdapter(customAdapter);
}
public void onClickBtn(@NonNull View v)
{
String searchString = "Kyle";
searchedList = new ArrayList<>();
for (int x = myModelList.size(), i = 0; i < x; ++i) {
if (myModelList.get(i).getName().equals(searchString)){
searchedList.add(myModelList.get(i));
}
}
customAdapter.updateList(searchedList);
customAdapter.setSearchMode(true);
}
}
I am mostly develop in kotlin so maybe some text error can happen in this code. you can check the logic for this requirement
Upvotes: 0