我正在尝试编写自己的recyclerview slector算法。到目前为止,除了处理第一个选择之外,我成功地设法编写了部分代码。基本上我想将背景设置为所选项目的蓝色,其他地方为白色(与ListView&#39的setSelection相同)。
所以,这个想法是:
一切正常,除了: 1.无法使用第一个视图初始化navMenuSelection。试图在onPostCreate方法中使用mDrawerLayout.getChildAt(0),但返回null
任何想法都将受到高度赞赏。
public class ActivityMain extends AppCompatActivity {
private View navMenuSelection = null; // Select current view
protected void onCreate(Bundle savedInstanceState) {
// ALL THE CODES TO DEFINE RECYCLERVIEW
mRecyclerView.addOnItemTouchListener(new RecycleTouchListener(this, new ClickListner() {
@Override
public void onClick(View view, int position) {
if(view != navMenuSelection){
setNavItemSelected(view);
removeNavItemSelected(navMenuSelection);
navMenuSelection = view;
mDrawerLayout.closeDrawers();
}
}
}));
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
navMenuSelection = mDrawerLayout.getChildAt(0);
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState){
//savedInstanceState.put???("currselection", navMenuSelection); // HOW TO DO THAT
super.onSaveInstanceState(savedInstanceState);
}
public void setNavItemSelected(View v){
if(v!= null) {
v.setBackgroundColor(R.color.BLUE));
}
}
public void removeNavItemSelected(View v){
if(v!= null) {
v.setBackgroundColor(R.color.WHITE));
}
}
}
适配器类(将onClick事件移至适配器后)
public class NavDrawerAdapter extends RecyclerView.Adapter<NavDrawerAdapter.ViewHolder> {
private String[] mNavTitles; // stores title
private int[] mIcons; // stores icon
private Context context;
private int oldpostion = 0;
public NavDrawerAdapter(Context context, String Titles[], int[] Icons){
this.context = context;
mNavTitles = Titles;
mIcons = Icons;
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
ImageView imageView;
public ViewHolder (View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.title);
imageView = (ImageView) itemView.findViewById(R.id.icon);
}
}
@Override
public NavDrawerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.navdrawer_item,parent,false);
return new ViewHolder(v,viewType);
}
@Override
public void onBindViewHolder(NavDrawerAdapter.ViewHolder holder, final int position) {
holder.textView.setText(mNavTitles[position]);
holder.imageView.setImageResource(mIcons[position]);
if(position == 0) {
setNavItemSelected(holder.itemView);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(position != oldpostion){
setNavItemSelected(v);
//removeNavItemSelected(OLD VIEW);
oldpostion = position;
}
}
});
}
@Override
public int getItemCount() {
return mNavTitles.length;
}
@Override
public int getItemViewType(int position) {
return 1;
}
public void setNavItemSelected(View v){
if(v!= null) {
v.setBackgroundColor(context.getResources().getColor(R.color.navdrawer_item_selected_bg));
TextView tview = (TextView) v.findViewById(R.id.title);
tview.setTextColor(context.getResources().getColor(R.color.navdrawer_item_selected_text));
}
}
public void removeNavItemSelected(View v){
if(v!= null) {
v.setBackgroundResource(R.drawable.list_selector_nav_drawer);
TextView tview = (TextView) v.findViewById(R.id.title);
tview.setTextColor(context.getResources().getColorStateList(R.color.list_selector_nav_drawer_text));
}
}
}
答案 0 :(得分:1)
关于你的问题:
RecyclerView
中获取您需要的视图,您可以使用mRecyclerView.findViewHolderForAdapterPosition(position)
。int
。我之前使用的另一种模式是向RecyclerView.Adapter
添加一个布尔数组,用于保存当前应激活哪些视图(与数据集合中的位置相关联)的信息。基于这个数组,我正在改变onBindViewHolder()
中的观点背景。
如果回收站视图足够短,可以在单个屏幕上看到,那么您当前的解决方案是可以的。但是一旦它开始回收它的旧观看者,你就会在未选择的视图中重复使用“选定”背景 - 所有这些都是因为你记住了视图,而不是连接到它们的数据位置。
修改强>
我将在这里放一些来自适配器的相关代码来说明我对实现的想法。在我的方法中,我使用了一个状态列表,可以使用“选定”背景绘制激活的状态,但你可以通过手动设置背景来完成所有操作。
public class RecyclerAdapter
extends RecyclerView.Adapter<RecyclerAdapter.YourViewHolder> {
private final List<...> data;
private final RecyclerAdapterCallbacks listener; //e.g. for activity callbacks
private final List<Boolean> activation;
public RecyclerAdapter(List<...> data, RecyclerAdapterCallbacks listener) {
this.data = data;
this.listener = listener;
this.activation = new ArrayList<>(data.size());
fillActivationList();
}
private void fillActivationList() {
int size = data.size();
for (int i = 0; i < size; i++) activation.add(false);
}
//------YourViewHolder implementation here------
public interface RecyclerAdapterCallbacks { //Callbacks interface if needed
void onRowSelected(... dataPiece);
void onRowDeselected();
}
@Override
public WordsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//your code
}
@Override
public void onBindViewHolder(YourViewHolder holder, final int position) {
holder.field.setText(data.get(position).getString());
holder.itemView.setActivated(activation.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Boolean previousState = activation.get(position);
deactivateAll();
activation.set(position, !previousState);
notifyDataSetChanged();
if (!previousState) {
listener.onRowSelected(data.get(position));
} else {
listener.onRowDeselected();
}
}
});
}
private void deactivateAll() {
Collections.fill(activation, false);
}
@Override
public int getItemCount() {
return data.size();
}
public void clearResults() {
notifyItemRangeRemoved(0, data.size());
data.clear();
activation.clear();
}
public void add(Word item) {
data.add(item);
notifyItemInserted(data.size() - 1);
activation.add(false);
}
答案 1 :(得分:0)
由于你已经在使用数组来传递你的图标和标题,让我们添加另一个数组来保存你当前的选择
private boolean isSelected[] = {true, false, false, false, false}; //make sure that the length of this array matches the length of navtitles and navicon. set the first element to true since you want the first item to be selected by default. you can declare this directly on the adapter if this is static
或者您可以将其作为参数传递
private boolean isSelected[];
public NavDrawerAdapter(Context context, String Titles[], int[] Icons, boolean[] isSelected){
this.context = context;
mNavTitles = Titles;
mIcons = Icons;
this.isSelected = isSelected;
}
....
@Override
public void onBindViewHolder(NavDrawerAdapter.ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int i=0; i < isSelected.length(); i++){
if (i==position){
isSelected[position]=true;
else
isSelected[position]=false;
}
notifyDataSetChanged();
}
});
if (isSelected[position]==true){
//execute your codes here
}else{
//execute your codes here
}
}
只是尝试调试是否有任何错误或拼写错误。我没有使用任何代码编辑器,所以可能会有一些错误
答案 2 :(得分:0)
为了方便您,我建议您只在视图中添加布局,这样您就可以更改布局的背景。不是最干净的方法,但这个应该为你做的伎俩
public class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
ImageView imageView;
LinearLayout layout; //whatever layout your using, just an example
public ViewHolder (View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.title);
imageView = (ImageView) itemView.findViewById(R.id.icon);
layout = (LinearLayout) itemView.findViewById(R.id.layout);
}
}
...
@Override
public void onBindViewHolder(NavDrawerAdapter.ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int i=0; i < isSelected.length(); i++){
if (i==position){
isSelected[position]=true;
else
isSelected[position]=false;
}
notifyDataSetChanged();
}
});
if (isSelected[position]==true){
//execute your codes here
holder.layout.setBackgroundResource(R.drawable.list_selector_nav_drawer);
holder.textView.setTextColor(context.getResources().getColorStateList(R.color.list_selector_nav_drawer_text));
}else{
//execute your codes here
holder.layout.setBackgroundResource(R.drawable.list_selector_nav_drawer);
holder.textView.setTextColor(context.getResources().getColorStateList(R.color.list_selector_nav_drawer_text));
}
}