android - 如何避免在 recyclerview 上滚动更改 textview 颜色和 Imageview 颜色?
问题描述
我正在使用 recyclerview 来实现我的列表项。在每个项目行中,我都有一个文本视图和一个时钟图标。我还有一个基准时间,我将每个 recyclerview 项目的时间与它进行比较。如果差值小于 30 分钟,则 textview 和时钟图标的颜色应变为黄色。我用这些代码行来做到这一点:
if(!isNear) {
time.setTextColor(context.getResources().getColor(R.color.yellow));
Drawable clockIcon= ContextCompat.getDrawable(context, R.drawable.clock);
clockIcon.setColorFilter(ContextCompat.getColor(context,R.color.yellow), PorterDuff.Mode.SRC_IN);
clockIc.setImageDrawable(clockIcon);
}
else {
time.setTextColor(context.getResources().getColor(R.color.white));
Drawable clockIcon= ContextCompat.getDrawable(context, R.drawable.clock);
clockIcon.setColorFilter(ContextCompat.getColor(context,R.color.white), PorterDuff.Mode.SRC_IN);
clockIc.setImageDrawable(clockIcon);
}
但是当我在 recyclerview 行中滚动时,textview 和时钟图标的颜色更改错误。我还使用一个数组来存储 isNear 变量的状态,但结果是相同的。我应该怎么办?
适配器代码:
public class BusTicketAdapter extends RecyclerView.Adapter<BusTicketAdapter.View_Holder> {
List<BusFromToResponse> availableBuses=new ArrayList<>();
List<BusFromToResponse> displayedBuses=new ArrayList<>();
private boolean[] toggledChoices;
TicketListener ticketListener;
Context context;
String str_date;
public BusTicketAdapter(List<BusFromToResponse> availableBuses,Context context,String str_date,TicketListener listener){
this.availableBuses.addAll(availableBuses);
displayedBuses.addAll(availableBuses);
toggledChoices=new boolean[displayedBuses.size()];
this.context=context;
this.str_date=str_date;
this.ticketListener=listener;
}
@Override
public BusTicketAdapter.View_Holder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.filler_bus_tickets, parent, false);
return new View_Holder(v);
}
@Override
public void onBindViewHolder(View_Holder holder, int position) {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"));
String timeC=c.getTime().toString();
int index=timeC.indexOf("+");
timeC=timeC.substring(index+1,index+6);
int hour=4;
String time=displayedBuses.get(position).getDepartureDate().substring(displayedBuses.get(position).getDepartureDate().indexOf("T")+1,
displayedBuses.get(position).getDepartureDate().indexOf("Z")-3);
if(timeC.contains("03:30"))
hour=3;
String[] hourmin=time.split(":");
int min=Integer.valueOf(hourmin[1])+30;
if(min>59){
min-=60;
hour+=1;
}
String minute=String.valueOf(min);
if(min<10)
minute="0"+minute;
hour+=Integer.valueOf(hourmin[0]);
if(hour>23)
hour=hour-24;
boolean isNear=DateUtil.IsBigger30Min(String.valueOf(hour)+":"+minute,c.getTime().getHours()+":"+c.getTime().getMinutes(),str_date);
toggledChoices[position]=isNear;
holder.time.setText((String.valueOf(hour).length()==1?"0"+String.valueOf(hour):String.valueOf(hour))+" : "+minute);
holder.onBind(displayedBuses.get(position),position);
if (position % 2 == 0) {
holder.rootView.setBackgroundColor(context.getResources().getColor(R.color.ticket_row1));
} else {
holder.rootView.setBackgroundColor(context.getResources().getColor(R.color.ticket_row2));
}
}
@Override
public int getItemCount() {
return displayedBuses.size();
}
class View_Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
ExtendedTextView time;
ViewGroup rootView;
ImageView clockIc;
View_Holder(View v) {
super(v);
rootView = v.findViewById(R.id.fillerBusTicket_root);
rootView.setOnClickListener(this);
clockIc=v.findViewById(R.id.clock_ic);
time=v.findViewById(R.id.time);
}
void onBind(BusFromToResponse bus,int position){
if(!toggledChoices[position]) {
time.setTextColor(context.getResources().getColor(R.color.yellow));
Drawable clockIcon= ContextCompat.getDrawable(context, R.drawable.clock);
clockIcon.setColorFilter(ContextCompat.getColor(context,R.color.yellow), PorterDuff.Mode.SRC_IN);
clockIc.setImageDrawable(clockIcon);
}
else {
time.setTextColor(context.getResources().getColor(R.color.white));
Drawable clockIcon= ContextCompat.getDrawable(context, R.drawable.clock);
clockIcon.setColorFilter(ContextCompat.getColor(context,R.color.white), PorterDuff.Mode.SRC_IN);
clockIc.setImageDrawable(clockIcon);
}
}
@Override
public void onClick(View v) {
ticketListener.onRowClicked(displayedBuses.get(getAdapterPosition()));
}
}
}
解决方案
解决此问题的一种方法是采用两个 viewHolder。
首先,设计两个独立的 XML 布局,一个用于 isNear,另一个用于另一个。例如:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
此布局是第一个布局。下一个是第二个。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorAccent"
android:text="TextView" />
</LinearLayout>
如果你仔细看,你会发现我已经为第二个更改了文本颜色以显示更改。
现在你必须为它们每个取两个 ViewHolders。例如:对于第一个:
public class FirstViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public FirstViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.textView);
}
}
我在这里链接了 XML 的 textView。现在,第二个 viewHolder:
public class SecondViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public SecondViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.textView);
}
}
在这里,我将这个与第二个 XML 文件链接起来。
现在,在适配器类中,您需要像这样扩展它:
public class NewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
在这里,您会看到我没有包含任何特定的 viewHolder,而是包含了通用RecyclerView.ViewHolder
类。现在,您必须重写getItemViewType
适配器类中的方法。例如:
@Override
public int getItemViewType(int position) {
if (isNear)
return 0;
else
return 1;
}
现在,您onCreateViewHolder
在适配器中的一个方法,您必须检查 viewType 并根据它返回 ViewHolder(View) 。例如:
if (viewType == 0) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.first_layout,
viewGroup, false);
return new FirstViewHolder(view);
} else {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.second_layout,
viewGroup, false);
return new SecondViewHolder(view);
}
现在,在您的onBindViewHolder
方法中,从 ArrayList 中获取元素并将其设置为 ViewHolder 的 Items。
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
if (isNear) {
FirstViewHolder holder = (FirstViewHolder) viewHolder;
holder.textView.setText("something you want to set");
} else {
SecondViewHolder holder = (SecondViewHolder) viewHolder;
holder.textView.setText("something you want to set");
}
}
试试这个,让我知道你是否解决了这个问题。
推荐阅读
- selenium - 尝试单击链接以在 selenium 中弹出窗口
- c# - Xamarin 中 QR 扫描后的处理对话框
- react-native - React Native Webview错误1002 mailto链接
- javascript - 我应该抓取数据并保存到数据库以访问动漫数据吗
- azure-ad-b2c - 是否需要添加来宾用户才能使用 Azure B2C 进行身份验证?
- maple - Maple 基础:变换 Maple 结果
- spring - 如何使用@PostAuthorize 将返回对象值与会话属性进行比较
- javascript - 如何从相等的属性返回结合自身的结果?
- c++ - unique_ptr 和内存分配失败
- pdf - 如何使用按需打印服务打印客户生成的个性化海报