Android 一旦数据在recyclerview适配器上更新,如何将字体从粗体改为普通?
我正在使用Firebase数据和Android 一旦数据在recyclerview适配器上更新,如何将字体从粗体改为普通?,android,firebase,firebase-realtime-database,android-recyclerview,android-adapter,Android,Firebase,Firebase Realtime Database,Android Recyclerview,Android Adapter,我正在使用Firebase数据和RecyclerViewAdapter 该场景是当用户单击列表时,初始状态为未读将更改为已读,因此字体应从粗体更改为普通 我当前将状态从未读更改为已读的后端流程正在运行并更新到Firebase,但是我的特定回收视图项的界面没有从粗体更改为正常 我的想法是,无需回调Firebase数据即可读取状态,但界面应根据用户单击进行更改 有人能帮我吗? NotificationActivity.java: package com.myapp.activity.notific
RecyclerView
Adapter
该场景是当用户单击列表时,初始状态为未读
将更改为已读
,因此字体
应从粗体
更改为普通
我当前将状态从未读
更改为已读
的后端流程正在运行并更新到Firebase,但是我的特定回收视图
项的界面没有从粗体
更改为正常
我的想法是,无需回调Firebase数据即可读取状态,但界面应根据用户单击进行更改
有人能帮我吗?
NotificationActivity.java
:
package com.myapp.activity.notification;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.material.nereeducation.R;
import com.material.nereeducation.adapter.AdapterNotification;
import com.material.nereeducation.model.Notification;
import com.material.nereeducation.utils.Tools;
import com.material.nereeducation.widget.LineItemDecoration;
import java.util.ArrayList;
import java.util.List;
public class NotificationActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private AdapterNotification mAdapter;
private ActionModeCallback actionModeCallback;
private ActionMode actionMode;
private Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification);
initToolbar();
initComponent();
Tools.setSystemBarColor(this, R.color.black);
}
private void initToolbar() {
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Notifications");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
private List<Notification> items = new ArrayList<>();
private LinearLayout messageEmptyList;
private void initComponent() {
messageEmptyList = findViewById(R.id.messageEmptyList);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new LineItemDecoration(this, LinearLayout.VERTICAL));
recyclerView.setHasFixedSize(true);
//set data and list adapter
mAdapter = new AdapterNotification(this, items);
recyclerView.setAdapter(mAdapter);
mAdapter.setOnClickListener(new AdapterNotification.OnClickListener() {
@Override
public void onItemClick(View view, Notification obj, int pos) {
if (mAdapter.getSelectedItemCount() > 0) {
enableActionMode(pos);
} else {
// read the inbox which removes bold from the row
Notification notification = mAdapter.getItem(pos);
Toast.makeText(getApplicationContext(), "Read: " + notification.sender_id, Toast.LENGTH_SHORT).show();
updateStatus(notification.notificationId,"read",pos);
}
}
@Override
public void onItemLongClick(View view, Notification obj, int pos) {
enableActionMode(pos);
}
});
actionModeCallback = new ActionModeCallback();
getNotificationData();
}
private void getNotificationData()
{
items.clear();
GsonBuilder builder = new GsonBuilder();
final Gson gson = builder.create();
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
String uuid = firebaseAuth.getUid();
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = firebaseDatabase.getReference();
databaseReference.child("notifications/"+uuid+"/data_notification").orderByChild("status").startAt("read").endAt("unread").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.getValue() != null)
{
for(DataSnapshot snapshot: dataSnapshot.getChildren())
{
String dataReceived = gson.toJson(snapshot.getValue());
Notification notificationItems = gson.fromJson(dataReceived, Notification.class);
items.add(notificationItems);
}
mAdapter.notifyDataSetChanged();
}else
{
messageEmptyList.setVisibility(View.VISIBLE);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void updateStatus(final String notificationId, String status, final int position) {
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
String uuid = firebaseAuth.getUid();
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = firebaseDatabase.getReference();
databaseReference.child("notifications/"+uuid+"/data_notification").child(notificationId).child("status").setValue(status
).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
mAdapter.notifyItemChanged(position); //Problem here - how to update text from BOLD to NORMAL for this item?
}
});
}
private void enableActionMode(int position) {
if (actionMode == null) {
actionMode = startSupportActionMode(actionModeCallback);
}
toggleSelection(position);
}
private void toggleSelection(int position) {
mAdapter.toggleSelection(position);
int count = mAdapter.getSelectedItemCount();
if (count == 0) {
actionMode.finish();
} else {
actionMode.setTitle(String.valueOf(count));
actionMode.invalidate();
}
}
private class ActionModeCallback implements ActionMode.Callback {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_delete, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_delete) {
deleteInboxes();
mode.finish();
return true;
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mAdapter.clearSelections();
actionMode = null;
}
}
private void deleteInboxes() {
List<Integer> selectedItemPositions = mAdapter.getSelectedItems();
for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
mAdapter.removeData(selectedItemPositions.get(i));
}
mAdapter.notifyDataSetChanged();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
} else {
Toast.makeText(getApplicationContext(), item.getTitle(), Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
}
package com.myapp.adapter;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateUtils;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.material.nereeducation.R;
import com.material.nereeducation.helper.AlphabetColor;
import com.material.nereeducation.model.Notification;
import com.material.nereeducation.utils.Tools;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class AdapterNotification extends RecyclerView.Adapter<AdapterNotification.ViewHolder> {
private Context ctx;
private List<Notification> items;
private OnClickListener onClickListener = null;
private SparseBooleanArray selected_items;
private int current_selected_idx = -1;
private AlphabetColor alphabetColor;
public void setOnClickListener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView from, title, message, date, image_letter;
public ImageView image;
public RelativeLayout lyt_checked, lyt_image;
public View lyt_parent;
public ViewHolder(View view) {
super(view);
from = view.findViewById(R.id.from);
title = view.findViewById(R.id.title);
message = view.findViewById(R.id.message);
date = view.findViewById(R.id.date);
image_letter = view.findViewById(R.id.image_letter);
image = view.findViewById(R.id.image);
lyt_checked = view.findViewById(R.id.lyt_checked);
lyt_image = view.findViewById(R.id.lyt_image);
lyt_parent = view.findViewById(R.id.lyt_parent);
}
}
public AdapterNotification(Context mContext, List<Notification> items) {
this.ctx = mContext;
this.items = items;
selected_items = new SparseBooleanArray();
alphabetColor = new AlphabetColor(mContext);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_notification, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final Notification notification = items.get(position);
// displaying text view data
System.out.println("sender type:"+notification.sender_type);
Character firstLetter;
if(notification.sender_type.equals("1")) //Admin
{
String admin = ctx.getString(R.string.admin_name);
holder.from.setText(admin);
firstLetter = admin.substring(0, 1).charAt(0);
holder.image_letter.setText(String.valueOf(firstLetter));
}else
{
holder.from.setText(notification.senderName);
firstLetter = notification.senderName.substring(0, 1).charAt(0);
holder.image_letter.setText(String.valueOf(firstLetter));
}
if(notification.status.equals("unread"))
{
holder.from.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
holder.title.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
holder.title.setText(notification.title);
holder.message.setText(notification.message);
holder.date.setText(getDate(Long.parseLong(notification.date)));
holder.lyt_parent.setActivated(selected_items.get(position, false));
holder.lyt_parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onClickListener == null) return;
onClickListener.onItemClick(v, notification, position);
}
});
holder.lyt_parent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onClickListener == null) return false;
onClickListener.onItemLongClick(v, notification, position);
return true;
}
});
toggleCheckedIcon(holder, position);
displayImage(holder, notification, firstLetter);
}
private void displayImage(ViewHolder holder, Notification notification, Character firstLetter) {
if (notification.image != null) {
Tools.displayImageRound(ctx, holder.image, notification.image);
holder.image.setColorFilter(null);
holder.image_letter.setVisibility(View.GONE);
} else {
holder.image.setImageResource(R.drawable.shape_circle);
holder.image.setColorFilter(alphabetColor.getColorByAlphabet(firstLetter), PorterDuff.Mode.MULTIPLY);
holder.image_letter.setVisibility(View.VISIBLE);
}
}
private String getDate(long time) {
Date date = new Date();
long currentTime = date.getTime();
String result = (String) DateUtils.getRelativeTimeSpanString(time, currentTime, 0);
return result;
}
private void toggleCheckedIcon(ViewHolder holder, int position) {
if (selected_items.get(position, false)) {
holder.lyt_image.setVisibility(View.GONE);
holder.lyt_checked.setVisibility(View.VISIBLE);
if (current_selected_idx == position) resetCurrentIndex();
} else {
holder.lyt_checked.setVisibility(View.GONE);
holder.lyt_image.setVisibility(View.VISIBLE);
if (current_selected_idx == position) resetCurrentIndex();
}
}
public Notification getItem(int position) {
return items.get(position);
}
@Override
public int getItemCount() {
return items.size();
}
public void toggleSelection(int pos) {
current_selected_idx = pos;
if (selected_items.get(pos, false)) {
selected_items.delete(pos);
} else {
selected_items.put(pos, true);
}
notifyItemChanged(pos);
}
public void clearSelections() {
selected_items.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount() {
return selected_items.size();
}
public List<Integer> getSelectedItems() {
List<Integer> items = new ArrayList<>(selected_items.size());
for (int i = 0; i < selected_items.size(); i++) {
items.add(selected_items.keyAt(i));
}
return items;
}
public void removeData(int position) {
items.remove(position);
resetCurrentIndex();
}
private void resetCurrentIndex() {
current_selected_idx = -1;
}
public interface OnClickListener {
void onItemClick(View view, Notification obj, int pos);
void onItemLongClick(View view, Notification obj, int pos);
}
}
对于这种情况,您还需要处理其他问题
if(notification.status.equals("unread")){
holder.from.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
holder.title.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}else{
holder.from.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
holder.title.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
}
如果您想在适配器中设置textview不同的字体或颜色,您需要检查每个位置,因此在您的情况下,您只需为textview设置粗体字体,就必须为默认textview字体重新设置普通字体 在adapter中将字体设置为正常 为textview设置文本默认字体,如下所示
holder.from.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
holder.title.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
然后检查项目状态是否为未读
if(notification.status.equals("unread")){
holder.from.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
holder.title.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
因此,我想您的问题是,状态(已读/未读)应用于数据库,但没有反映在recycler视图上 如果这是问题所在,主要是因为您没有处理列表的数据更改方法(并使用新值更新它) 您当前正在使用此选项获取数据:
databaseReference.child("notifications/"+uuid+"/data_notification").orderByChild("status").startAt("read").endAt("unread").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {.....
这不会帮助您控制更改的项目
可能的解决方案
解决此问题的一种方法是使用(FirebaseUI)数据库而不是自定义适配器
FirebaseUI将侦听更改并更新列表
编辑2
对单值事件使用ChildEventListener而不是Listener
与此相反:
databaseReference.child("notifications/"+uuid+"/data_notification").orderByChild("status").startAt("read").endAt("unread").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {.....
使用以下命令:
databaseReference.child("notifications/"+uuid+"/data_notification").orderByChild("status").startAt("read").endAt("unread").addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot) {.....
//add items to list (like you did)
@Override
public void onChildChanged(DataSnapshot dataSnapshot) {.....
//set the items again to the list (update them here) and notify
//data set changed (so values update in your list).
我相信你应该这样设置字体:
if ("unread".equals(notification.status)) {
holder.from.setTypeface(null, Typeface.BOLD);
holder.title.setTypeface(null, Typeface.BOLD);
} else {
holder.from.setTypeface(null, Typeface.NORMAL);
holder.title.setTypeface(null, Typeface.NORMAL);
}
该视图正被
RecyclerView
重新使用,因此,一旦将字体设置为粗体,您需要在下次使用该视图时将其设置回正常状态。为什么要向下投票?有什么原因吗?结果还是一样。。。我的意思是,在数据更改后,粗体仍然没有更改为Normal您确定已经将新值更新到适配器吗?mAdapter.notifyItemChanged(位置);似乎您刚刚告诉适配器使用旧数据刷新。您需要先更新该行的notification.status,然后调用mAdapter.notifyItemChanged(position)无更改,我的意思是在数据更改后,粗体仍不能更改为正常。。。如何仅直接更改该项而不是使用item.clear()
?item.clear()的需要是什么;您可以使用刚刚设置的适配器引用单个位置。notifyItemChanged(int-position)我尝试过,但该项目没有刷新。但风格还是一样。我认为称为的旧数据没有更新。如何在调用方法updateStatus()
后才能像text.setText(“新数据”)
那样设置该项?我认为您的数据正在刷新,但问题是您没有更新arraylist位置,您还必须更新特定职位以反映数据。是否打印notification的值。在参考数据后,该特定职位的状态您将了解实际问题出在何处如何使用FirebaseUI?我们能不能只关注recyclerview?