其实多选和单选,还有一种就是利用RecyclerView的单条刷新方法,notifyItemChanged().
只是单选的时候不是很好看,会出现选择了新的一个item之后,上一个item会出现一个上次被选择消失很慢的动画。
单选思路:保存前一次点击的item,每次判断是否被点击过,先将前一次的状态置为未选中,然后选中新的一条,就实现了单选。
多选思路:给一个selected状态,每次修改单条数据的状态,利用notifyItemChanged()刷新,然后将选中状态的数据遍历出来。(也可以在创建Adapter时候初始化一个selectedList,选中就增加,取消就删除)
在我们平时的开发中可能会用到简单的列表单选功能,ListView没有去尝试过,这里介绍下RecyclerView的单选功能。
我们是在Adapter中实现单选
public class ChoicePopupwindowAdapter extends RecyclerView.Adapter<ChoicePopupwindowAdapter.ChoicePopupwindowViewHolder> {
private Context context;
private List<HashMap<String,Object>> list;
private LayoutInflater inflater;
private OnPopupwindowItemListener listener = null;
//被选中的item的位置,设置初始值为-1是为了解决默认第一个被选中的问题
private int layoutPosition = -1;
public ChoicePopupwindowAdapter(Context context,List<HashMap<String,Object>> list){
this.context = context;
this.list = list;
this.inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* 设置点击事件
* @param listener
*/
public void setOnItemClickListener(OnPopupwindowItemListener listener){
this.listener = listener;
}
@Override
public ChoicePopupwindowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ChoicePopupwindowViewHolder(inflater.inflate(R.layout.choice_popupwindow_list_item,null));
}
@Override
public void onBindViewHolder(final ChoicePopupwindowViewHolder holder, int position) {
//item的点击事件
holder.itemView.setTag(position);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
layoutPosition = holder.getLayoutPosition();
notifyDataSetChanged();
if(listener != null){
listener.onItemClick(v, (Integer) v.getTag());
}
}
});
holder.tvChoice.setText(list.get(position).get("name").toString());
//更新单选之后的效果
if(position == layoutPosition){
holder.tvChoice.setTextColor(context.getResources().getColor(R.color.all_actionbar_color));
holder.ivChoice.setVisibility(View.VISIBLE);
holder.ivChoice.setImageResource(R.drawable.select_hook_icon);
}else{
holder.tvChoice.setTextColor(context.getResources().getColor(R.color.text_balck));
holder.ivChoice.setVisibility(View.INVISIBLE);
holder.ivChoice.setImageResource(R.drawable.select_hook_icon);
}
}
@Override
public int getItemCount() {
return list.size();
}
public class ChoicePopupwindowViewHolder extends RecyclerView.ViewHolder{
TextView tvChoice;
ImageView ivChoice;
public ChoicePopupwindowViewHolder(View itemView) {
super(itemView);
tvChoice = (TextView) itemView.findViewById(R.id.tv_choice);
ivChoice = (ImageView) itemView.findViewById(R.id.iv_choice);
}
}
//==================此处代码就是更新选中位置====================
/**
* 更新选中位置
* @param selectedPosition
*/
public void setSelectedPosition(int selectedPosition) {
this.layoutPosition = selectedPosition;
}
}
我是在PopupWindow实现的单选,顺便将PopupWindow的代码贴出来,可以实现给PopupWindow添加暗色背景的效果。
public class ChoicePopupWindow extends PopupWindow {
private Activity activity;
private List<HashMap<String,Object>> list;
private LayoutInflater inflater;
private View view;
private int width;
private int height;
private RecyclerView rvList;
private RecyclerView.LayoutManager layoutManager;
private DividerListItemDecoration decoration;
private ChoicePopupwindowAdapter adapter;
private OnPopupwindowSelectListener listener = null;
public ChoicePopupWindow(Activity activity, List<HashMap<String,Object>> list) {
super(activity);
this.activity = activity;
this.list = list;
init();
}
private void init() {
inflater = LayoutInflater.from(activity);
view = inflater.inflate(R.layout.choice_popupwindow_layout, null);
this.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
// 获取测量后的宽度
width = view.getMeasuredWidth();
//获取测量后的高度
height = view.getMeasuredHeight();
//设置背景为透明
this.setBackgroundDrawable(new ColorDrawable(0x66000000));
setBackGround(0.5f);
//在PopupWindow里面就加上下面代码,让键盘弹出时,不会挡住pop窗口。
this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
this.setFocusable(true);
this.setOutsideTouchable(true);
this.setContentView(view);
rvList = (RecyclerView) view.findViewById(R.id.rv_list);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ScreenUtils.getScreenWidth(activity)/2, ViewGroup.LayoutParams.WRAP_CONTENT);
rvList.setLayoutParams(params);
layoutManager = new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false);
rvList.setLayoutManager(layoutManager);
decoration = new DividerListItemDecoration(activity, DividerListItemDecoration.VERTICAL_LIST, R.drawable.divider_vertical_list);
rvList.addItemDecoration(decoration);
adapter = new ChoicePopupwindowAdapter(activity, list);
rvList.setAdapter(adapter);
adapter.setOnItemClickListener(itemListener);
//需要在PopupWindow消失的时候,将窗口的背景修改为不透明
this.setOnDismissListener(dismissListener);
}
/**
* 设置背景透明度
*
* @param alpha
*/
private void setBackGround(float alpha) {
Window window = activity.getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.alpha = alpha;
if (alpha == 1f) {
//不移除该Flag的话,在有视频的页面上的视频会出现黑屏的bug
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
} else {
//解决在华为手机上半透明效果无效的bug
window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
window.setAttributes(params);
}
/**
* PopupWindow消失监听
*/
OnDismissListener dismissListener = new OnDismissListener() {
@Override
public void onDismiss() {
//修改窗口透明度为不透明
setBackGround(1f);
}
};
/**
* item点击事件
*/
OnPopupwindowItemListener itemListener = new OnPopupwindowItemListener() {
@Override
public void onItemClick(View view, int position) {
if(listener != null){
listener.onSelectValue(position);
}
}
};
/**
* 设置选中监听
*
* @param listener
*/
public void setOnSelectListener(OnPopupwindowSelectListener listener) {
this.listener = listener;
}
/**
* 判断选择窗是否正在运行
*
* @return
*/
public boolean isPopupWindowShowing() {
return this.isShowing();
}
/**
* 显示方法 并且控制显示位置
*
* @param view
*/
public void show(View view) {
this.showAsDropDown(view,width,height,Gravity.RIGHT|Gravity.TOP);
}
/**
* 取消选择窗
*/
public void cancel() {
if (isPopupWindowShowing()) {
this.dismiss();
adapter = null;
}
}
/**
* 更新选中位置
*
* @param selectedPosition 选中位置
*/
public void updatePosition(int selectedPosition) {
if (adapter != null) {
//设置单选位置,并且刷新列表
adapter.setSelectedPosition(selectedPosition);
adapter.notifyDataSetChanged();
}
}
}
注意:有的时候我们在使用PopupWindow或者Dialog(DialogFragment)的时候,可能存在输入窗,我们需要在dialog或者PopupWindow消失的时候隐藏键盘,可以在声明周期方法的onDestroy()中调用隐藏键盘。
@Override
public void onDestroy() {
super.onDestroy();
KeyboardUtils.hideSoftInput(activity);
if(dialog != null){
dialog.dismiss();
dialog = null;
}
}
//============隐藏软键盘的方法===========
/**
* 动态隐藏软键盘
*
* @param activity activity
*/
public static void hideSoftInput(final Activity activity) {
View view = activity.getCurrentFocus();
if (view == null) {
view = new View(activity);
}
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
if (imm == null) {
return;
}
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
RecyclerView实现多选
可以在这里说一下多选的功能的思路,实现多选我们可以给列表的实体类中增加一个select(Boolean型,初始化为false)状态,实现点击事件的时候修改select状态并且adapter.notifyDataSetChanged()刷新列表就欧克。
public class NewServiceTaskAdapter extends RecyclerView.Adapter<NewServiceTaskAdapter.NewServiceTaskViewHolder> {
private Context context;
private List<NewCreateService> list;
private LayoutInflater inflater;
private OnRecyclerItemListener listener = null;
public NewServiceTaskAdapter(Context context,List<NewCreateService> list){
this.context = context;
this.list = list;
this.inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* 设置监听
* @param listener
*/
public void setOnItemClickListener(OnRecyclerItemListener listener){
this.listener = listener;
}
/**
* 刷新列表数据
* @param list
*/
public void updateList(List<NewCreateService> list){
this.list = list;
notifyDataSetChanged();
}
@Override
public NewServiceTaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new NewServiceTaskViewHolder(inflater.inflate(R.layout.create_service_task_item_layout,null));
}
@Override
public void onBindViewHolder(final NewServiceTaskViewHolder holder, int position) {
holder.itemView.setTag(position);
holder.itemView.setOnClickListener(onClickListener);
holder.tvName.setText(list.get(position).getName());
holder.tvNum.setText("数量"+list.get(position).getNum()+"个");
if(list.get(position).isSelect()){
holder.ivCheck.setImageResource(R.drawable.select_icon);
}else{
holder.ivCheck.setImageResource(R.drawable.circle_icon);
}
}
@Override
public int getItemCount() {
return list.size();
}
class NewServiceTaskViewHolder extends RecyclerView.ViewHolder{
TextView tvName;
TextView tvNum;
ImageView ivCheck;
public NewServiceTaskViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tv_name);
tvNum = (TextView) itemView.findViewById(R.id.tv_num);
ivCheck = (ImageView) itemView.findViewById(R.id.iv_check);
}
}
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null){
listener.onItemClick(v, (Integer) v.getTag());
}
}
};
/**
* 遍历取出选中数据
* @return
*/
public List<NewCreateService> getList(){
List<NewCreateService> services = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if(list.get(i).isSelect()){
NewCreateService service = list.get(i);
service.setPosition(i);
services.add(service);
}
}
return services;
}
}
然后在RecyclerView的点击事件中去修改多选状态
createService = list.get(position);
//修改多选状态,选中或者未选中
createService.setSelect(!createService.isSelect());
//将修改的数据设置进list
list.set(position,createService);
//更新列表
adapter.updateList(list);