一.效果
二.实现
通过长按GridView中的item,触发Contextual ActionBar,既可对GridView中的数据进行批处理。
这里,需要给GridView设置MultiChoiceModeListener这个监听,可在此Listener中处理Contextual ActionBar Action Button的事件。他能监听到GridView中item的状态改变,方便我们做相关处理。
-
GridView里的Item有一个布局,包括了一个ImageView跟一TextView。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="120dp"
android:gravity="center"
android:orientation="vertical"
android:padding="8dp" >
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/action_settings" />
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/textbackground"
android:text="@string/showText"
android:textColor="#01700f" />
</RelativeLayout>
2. 定义一个MultiListItem,代表每一个Item。在这里加载item的布局,以及实现对item的背景,ImageView跟TextView的操作。
public class MultiListItem extends LinearLayout implements Checkable {
public ImageView mImg = null;
public TextView mText = null;
public boolean isChecked = false;
public MultiListItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater.from(context).inflate(R.layout.item_gridview, this);
mImg = (ImageView) findViewById(R.id.img);
mText = (TextView) findViewById(R.id.text);
}
public MultiListItem(Context context) {
this(context, null, 0);
}
public MultiListItem(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@Override
public void setChecked(boolean checked) {
setBackgroundResource(checked ? R.drawable.item_checked_effect
: android.R.color.transparent);
isChecked = checked;
}
@Override
public boolean isChecked() {
return isChecked;
}
@Override
public void toggle() {
setChecked(!isChecked);
}
public void setImgViewRes(int resid) {
if (mImg != null)
mImg.setBackgroundResource(resid);
}
public void setTextViewText(int text) {
if (mText != null)
mText.setText(text);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:orientation="vertical"
tools:context="com.saya.mutipchoice.MainActivity"
tools:ignore="MergeRootFrame" >
<GridView
android:id="@+id/gridView"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:cacheColorHint="#000000"
android:choiceMode="multipleChoiceModal"
android:horizontalSpacing="3dp"
android:numColumns="3"
android:verticalSpacing="12dp" >
</GridView>
<Button
android:id="@+id/btnPlayAgain"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:onClick="playItAgain"
android:text="@string/button_playagain" />
</LinearLayout>
public class MultiAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<MultiListItem> mItems;
private SparseBooleanArray mSelected;
public MultiAdapter() {
}
public MultiAdapter(Context context, ArrayList<MultiListItem> items) {
mContext = context;
mItems = items;
mSelected = new SparseBooleanArray();
}
@Override
public int getCount() {
return mItems.size();
}
@Override
public MultiListItem getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public void disSelectAll() {
mSelected.clear();
}
public void delete() {
ListIterator<MultiListItem> ite = mItems.listIterator();
while (ite.hasNext()) {
MultiListItem next = ite.next();
if (next.isChecked()) {
ite.remove();
}
}
notifyDataSetChanged();
}
public void select(int position) {
mItems.get(position).isChecked = true;
mSelected.put(position, true);
}
public void setSelect(int position, boolean check) {
mItems.get(position).isChecked = check;
mSelected.put(position, check);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
MultiListItem item = null;
if (convertView == null) {
item = new MultiListItem(mContext);
} else {
item = (MultiListItem) convertView;
}
item = getItem(position);
item.setChecked(mSelected.get(position));
return item;
}
}
public class MainActivity extends Activity {
private GridView gridView;
private MultiAdapter adapter;
private Context mContext = this;
private ArrayList<MultiListItem> mItems = new ArrayList<MultiListItem>();
private Button btnPlayAgain;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnPlayAgain = (Button) findViewById(R.id.btnPlayAgain);
prepareCats();
init();
}
MultiListItem item = null;
private void prepareCats() {
for (int i = 0; i <= 3; i++) {
item = new MultiListItem(mContext);
Field field;
try {
field = R.drawable.class.getField("images" + i);
item.setImgViewRes(field.getInt(null));
mItems.add(item);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
private void init() {
btnPlayAgain.setEnabled(false);
gridView = (GridView) findViewById(R.id.gridView);
gridView.setMultiChoiceModeListener(new OnMultiChoice());
adapter = new MultiAdapter(mContext, mItems);
gridView.setAdapter(adapter);
}
public void playItAgain(View view) {
prepareCats();
init();
}
class OnMultiChoice implements MultiChoiceModeListener {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
menu.findItem(R.id.action_selectall).setEnabled(
gridView.getCheckedItemCount() != gridView.getCount());
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_delete) {
adapter.delete();
mode.finish();
} else if (id == R.id.action_selectall) {
for (int i = 0; i < gridView.getCount(); i++) {
gridView.setItemChecked(i, true);
adapter.select(i);
}
} else if (id == R.id.action_disSelectall) {
for (int i = 0; i < gridView.getCount(); i++) {
gridView.setItemChecked(i, false);
}
adapter.disSelectAll();
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
adapter.disSelectAll();
if (adapter.getCount() == 0) {
btnPlayAgain.setEnabled(true);
}
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
adapter.setSelect(position, checked);
mode.setTitle(gridView.getCheckedItemCount() + "");
mode.invalidate();
}
}
}
三.TIPS
-
萌萌的catty背景如何实现?
很简单,在drawable中定义一个shape即可。
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#50000000" />
<stroke android:color="#00000000" />
</shape>
一般我们定义颜色值都是6位,这里出现了8位的颜色值。其实这个8位颜色值用处很大,他的后6位还是代表RGB颜色值,而前两位代表透明度,00是最高透明度,越增加,透明度越小。
2. 酷炫的选中效果如何实现?
也是一个shape搞定。最外边的边框用到stroke属性,圆角用到corners,颜色的梯度显示用到gradient,solid则像一层蒙板。
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#60000000" />
<corners android:radius="3dp" />
<gradient
android:angle="270"
android:endColor="#017cfd"
android:startColor="#00000000"
android:type="linear" />
<stroke
android:width="1dp"
android:color="#017cfd" />
</shape>
四.注意
-
给GridView设置choiceMode为CHOICE_MODE_MULTIPLE_MODAL,让GridView处于一个多选择模式。可以通过xml设置
android:choiceMode="multipleChoiceModal"
或者Java代码
gridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
2. 在Adapter中给每个item加载资源的时候,注意不要硬编码,否则删除的时候adapter无法准确删除。很多时候我们为了图省事,就直接在adapter中去给每个item赋值,如果只是展示效果,看不出不妥,但是一旦要动态操作数据,就出问题了。