android 多选功能小姐

多选功能小姐

其实不是小姐,是小节。

这周接到一个需求,完成一个多选删除以及多选转发的功能。删除以及转发的功能已经有了,注意是要实现多选的操作。

先说多选

这里的界面是ListView + CursorAdapter 实现的。我需要在 ListViewItemView 里面加一个CheckBox.

不得不提一下,这里的布局写的非常的混乱。里面包含多种类型的Item的,理论上,使用不同的ItemType去加载不同的ItemView是非常合适的。但是原来的界面不是这样玩的。是直接在一个ItemView里面通过逻辑去判断显示或者隐藏那部分View. 行吧,这样也是可以的,只是布局就比较混乱了。然后更糟糕的是,这里的布局还分左右两种情况,然后布局是同一个布局,然后在代码里面动态改变。具体怎么改的呢?

if (pos == RIGHT) {
    
    lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); // 添加该规则
    lp.addRule(RelativeLayout.RIGHT_OF, 0); // 屏蔽该规则
} else {
   
    lp.addRule(RelativeLayout.RIGHT_OF, R.id.item_check);
    lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
}

这段代码涉及到 RelativeLayout.LayoutParams.addRule()这个方法。这个方法很有意思。尤其是带两个参数的。如果第二个参数是0,说明这个规则不起作用。这样做有什么意义呢?意义就在于,如果之前添加了这个规则,通过这样的方式,可以让之前添加的该规则失效。

先把Checkbox放置到正确的位置。

好了,既然是这样的方式。我的CheckBox又是需要加在每个ItemView的最左边的。那么我就也按照addRule的方式,把我的Checkbox放到对应的位置上面去了。

然后要根据不同的Item类型,设置Checkbox的状态。

分别是不可用,未选中,选中 这3种状态。

这个要怎么弄呢?我先是根据对应的POJO对象,在里面添加一个属性int checkState;去处理的。但是,一直不行,滑动之后,选中状态全部混乱了。我猜想不可行的原因可能是,这里的POJO对象是根据Cursor生成的。而根据Cursor生成,又会将之前设置的checkState恢复为默认值。(这个只是猜想,没有去验证。)

既然此路不通,我就变通一下。我不再去设置对应的POJO对象的checkState属性了。我专门搞了一个成员变量HashMap<Integer,Integer>.其中的映射关系是:{key:position,value:checkState};这样就靠谱了。你不是根据Cursor去生成对应的POJO对象的吗,行。我的position也是通过Cursor拿到的。int position = cursor.getPosition();然后可不可用,是具体原有的逻辑来的。比如:int checkState = item.checkable? 0:1; 这样,可用不可用状态就搞定了。但是,用户点击选中的状态还是没有保存。

那么就通过设置Checkbox的点击事件去做这件事。

cb.setOnclickListener(v->{
    // 代码中将 0,1,2 定义成常量了,这里是为了验证效果
    // 0 - disable
    // 1 - unChekced
    // 2 - checked
	checkMap.put(pos, checkMap.get(pos)==1? 2:1);
	cb.setChecked(checkMap.get(pos) == 2); 
});

好了, 通过设置点击事件,也将CheckBox的选中不选中状态保存了。
到此为止,checkbox的3种状态都搞定了,列表怎么滑动都不会出现选中状态错乱的问题了。

至于样式,这个直接在布局里面设置对应的style去控制的。但是实际上滚动之后,样式不对了,我又在代码里面 cb.setXXX(); 之后调用了cb.setButtonDrawable(R.drawable.cb_multi_selector);

那么,现在就要把之前多选对应的数据给获取到,一遍后续的删除,转发操作的执行。

那么,之前保存的,只是{position:checkState} ,现在要拿到数据,那很简单。根据对应的position以及 checkState == 2然后把对应的POJO对象存起来即可。

做法就是弄一个成员变量private List<Bean> selectedList = new ArrayList<>; , 然后在CheckBox的点击事件里面做对应的list.add(bean); / list.remove(Bean);的操作即可。

cb.setOnClickListener(v->{
	// ... 设置选中状态的逻辑先
	if( checkMap.get(position) == 2 ) {
		selectedList.add(bean);
	} else {
		selectedList.remove(bean);
	}
});

OK , 这样一来,就把选中的数据给保存了。

然后在执行删除的时候,就去执行删除操作:ItemUtils.delete(seletedList);
执行转发的时候,也是去执行转发:ItemUtils.forward(selectedList);

多说一句,在执行多选删除的时候,这里是执行了数据操作。涉及到一个批处理操作。原有的逻辑是删除单条数据的,没有批处理。而这里就需要使用批处理了。不然每次删除一个都会触发删除成功的回调,非常烦人。

这里用到了ContenResolver.applyBatch();的操作。
public ContentProviderResult[] applyBatch(@NonNull String authority,
        @NonNull ArrayList<ContentProviderOperation> operations){}

authority: 这个不用说的, contenProvider 必然会配置这个
operations 这个就是待处理的数据集合

ContentProviderOperation的操作还是比较简单的,没有用过也能立即明白。

这里既然是删除,那就是 ContentProviderOperation.newDelete(uri).build(); 里面还有 withXXX()这样的辅助方法。(我觉得withXXX是给newUpdate()用的。)

这些参数构造完成了,调用一下 ContenResolver.applyBatch(authorty,ops);即可。

至于转发,这里完全是一个原有逻辑,不说了。


这个小姐大致就是这样子了。错了,是小节

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 应用中实现多日历,可以使用 Android 自带的 CalendarView 控件和自定义适配器。以下是实现多日历的一般步骤: 1. 在布局文件中添加 CalendarView 控件。 2. 在 MainActivity 类中获取 CalendarView 控件的引用,并设置其日期变更监听器。 3. 创建一个自定义适配器类来显示日历上的日期,并处理多日期的逻辑。 4. 在适配器类中,实现自定义的日期择逻辑,例如通过设置特定的背景颜色来表示中的日期。 5. 在 MainActivity 类中,将创建的适配器设置为 CalendarView 控件的适配器。 下面是一个简单的示例代码,展示如何实现多日历: **activity_main.xml** ```xml <CalendarView android:id="@+id/calendarView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` **MainActivity.java** ```java public class MainActivity extends AppCompatActivity { private CalendarView calendarView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); calendarView = findViewById(R.id.calendarView); // 设置日期变更监听器 calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() { @Override public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) { // 处理日期择逻辑 Toast.makeText(MainActivity.this, "择的日期:" + year + "-" + (month + 1) + "-" + dayOfMonth, Toast.LENGTH_SHORT).show(); } }); // 设置自定义适配器 calendarView.setShowWeekNumber(false); calendarView.setFirstDayOfWeek(Calendar.MONDAY); calendarView.setMinDate(System.currentTimeMillis() - 1000); calendarView.setDate(System.currentTimeMillis()); calendarView.setMaxDate(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * 365)); CustomCalendarAdapter adapter = new CustomCalendarAdapter(this); calendarView.setCustomDayView(adapter); } } ``` **CustomCalendarAdapter.java** ```java public class CustomCalendarAdapter implements CalendarViewAdapter { private LayoutInflater inflater; private HashSet<Long> selectedDates; // 中的日期集合 public CustomCalendarAdapter(Context context) { inflater = LayoutInflater.from(context); selectedDates = new HashSet<>(); } @Override public View getDayView(ViewGroup parent, int viewType) { // 创建并返回日期视图 return inflater.inflate(R.layout.custom_day_view, parent, false); } @Override public void bindDayView(View dayView, CalendarDay calendarDay) { TextView tvDay = dayView.findViewById(R.id.tvDay); // 显示日期 tvDay.setText(String.valueOf(calendarDay.getDay())); // 处理多日期逻辑 if (selectedDates.contains(calendarDay.getDate().getTime())) { dayView.setBackgroundResource(R.drawable.selected_day_bg); } else { dayView.setBackgroundResource(android.R.color.transparent); } // 添加日期点击监听器 dayView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (selectedDates.contains(calendarDay.getDate().getTime())) { selectedDates.remove(calendarDay.getDate().getTime()); dayView.setBackgroundResource(android.R.color.transparent); } else { selectedDates.add(calendarDay.getDate().getTime()); dayView.setBackgroundResource(R.drawable.selected_day_bg); } } }); } @Override public void onDateRangeSelected(@NonNull SimpleMonthAdapter.SelectedDays<CalendarDay> selectedDays) { // 必须实现此方法 } @Override public int indexOf(CalendarDay day) { // 必须实现此方法 return -1; } } ``` **custom_day_view.xml** ```xml <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tvDay" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textColor="@android:color/white" android:textSize="16sp" /> ``` 在上面的示例中,我们创建了一个 CustomCalendarAdapter 类来自定义日历中的日期视图,并处理多日期的逻辑。具体来说,我们在 bindDayView() 方法中处理日期的背景颜色,以表示其是否被中。在 onClick() 方法中,我们添加了一个点击监听器来处理日期的中和取消中操作。最后,在 MainActivity 类中,我们设置了自定义适配器,并将其设置为 CalendarView 控件的适配器。 这只是一个简单的示例,实际情况中可能需要更复杂的逻辑来实现多日历。但是,以上的代码可以作为一个起点来帮助你开始实现多日历功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值