ListView多选操作模式详解CHOICE_MODE_MULTIPLE与CHOICE_MODE_MULTIPLE_MODAL

转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1105/1906.html


一、在不使用ListView多选模式的情况下

注:我认为这一节可以不看,因为我觉得不使用ListView的多选模式有点愚蠢。

如果我们不知道ListView自带多选模式,那么我们一般是通过维护一个保存被选择position集合来实现多选的,通常情况下这个集合类型我们选择HashSet。

实现的大致框架如下:

Adapter中:

保存被选择的position


1
public HashSet<Long> selectedItems = new HashSet<Long>();


getView中判断当前Position是否在集合中,从而显示不同的外观


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
     public View getView(int position, View convertView, ViewGroup par) {
......
             if (selectedItems.contains((long)position)){
                 holder.cBox.setChecked( true );
             } else {
                 holder.cBox.setChecked( false );
             }
             if (selectedMode==AppContext.MULTI_SELECTED){
                 holder.cBox.setVisibility(View.VISIBLE);
                 holder.check_box_wraper.setVisibility(View.VISIBLE);
             } else {
                 holder.cBox.setVisibility(View.GONE);
                 holder.check_box_wraper.setVisibility(View.GONE);
             }
.....

Activity中:

主要是处理onItemClick事件,在不同模式下,做不同的处理。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
     //普通模式 :直接打开一个activity
         if (itemClickActionMode==AppContext.VIEW_NOTE){
             Long mId=Long.parseLong(idText.getText().toString());
             Uri uri = ContentUris.withAppendedId(getIntent().getData(), mId);
             startActivity( new Intent(Intent.ACTION_VIEW, uri));
         }
         //多选模式:更新adapter中selectedItems 集合的值,同时 让adapter在getView中改变item的外观。
        else {
             ViewHolder vHollder = (ViewHolder) v.getTag();
             if (mAdapter.selectedItems.contains((long)position)){
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
                 mAdapter.selectedItems.remove((long)position);
             } else {
                         mAdapter.selectedItems.add((long)position);
             }
             mAdapter.notifyDataSetChanged();
             onItemSelected(getSelectedCount());    
         }
     }


上面的做法其实用的很普遍。但是我们不提倡。


二、使用ListViiewCHOICE_MODE_MULTIPLE模式


ListView有四种模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
  * Normal list that does not indicate choices
  */
public static final int CHOICE_MODE_NONE = 0;
/**
  * The list allows up to one choice
  */
public static final int CHOICE_MODE_SINGLE = 1;
/**
  * The list allows multiple choices
  */
public static final int CHOICE_MODE_MULTIPLE = 2;
/**
  * The list allows multiple choices in a modal selection mode
  */
public static final int CHOICE_MODE_MULTIPLE_MODAL = 3;


其中CHOICE_MODE_NONE是普通模式,CHOICE_MODE_SINGLE是单选模式,不常用,CHOICE_MODE_MULTIPLECHOICE_MODE_MULTIPLE_MODAL都是多选模式,他们的区别稍后我们会讲到。

所以ListView在设计的时候其实是考虑了多选操作的,我们没有必要自己再像第一节描述的那样专门维护一个HashSet来保存被选择的position。实现ListView的多选操作的代码在ListView直接父类AbsListView中,AbsListView已经有一个mCheckStates变量来做了保存被选择的position这个事情。mCheckStates的定义如下:


1
SparseBooleanArray mCheckStates;

AbsListView还定义了如下公共方法:

//判断一个item是否被选中

1
public boolean isItemChecked(int position);

//获得被选中item的总数

1
public int getCheckedItemCount();

//选中一个item

1
public void setItemChecked(int position, boolean value);

//清除选中的item

1
public void clearChoices();


当点击一个item的时候absListView中会调用performItemClick,如果是CHOICE_MODE_MULTIPLE,则该item点击一次,mCheckStates中相应位置的状态变更一次。然后我们就可以通过listView的getCheckedItemCount()方法获取选择了多少个;isItemChecked(int position)方法判断一个item是不是被选中。

有了这些原生sdk的支持,难道还有什么多选操作是不能实现的吗?所以是不是应该考虑放弃第一节中描述的那种方法了呢?遗憾的是很多android开发者即使是用了CHOICE_MODE_MULTIPLE,仍然没有去利用这些ListView自带的功能,估计是根本不知道该CHOICE_MODE_MULTIPLE的 特性吧,这其实也是android程序员与ios程序员真正存在差距的地方。


CHOICE_MODE_MULTIPLE实战


先看看效果图


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.example.listmultichoise;
import android.os.Bundle;
import android.app.ActionBar;
import android.app.Activity;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ChoiceModeMultipleActivity extends Activity {
     ListView mListView = null ;
     MyListAdapter mAdapter;
     private View mMultiSelectActionBarView;
     private TextView mSelectedCount;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
         setContentView(R.layout.activity_list);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
         mListView = (ListView)findViewById(R.id.list);
         mAdapter = new MyListAdapter( this ,mListView);
         mListView.setAdapter(mAdapter);
         mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
         mListView.setOnItemClickListener( new OnItemClickListener() {
             public void onItemClick(AdapterView<?> parent, View view, int position,
                     long id) {
                 mAdapter.notifyDataSetChanged();
                 updateSeletedCount();
             }
         });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
         if (mMultiSelectActionBarView == null ) {
             mMultiSelectActionBarView = LayoutInflater.from(ChoiceModeMultipleActivity. this )
                 .inflate(R.layout.list_multi_select_actionbar, null );
             mSelectedCount =
                 (TextView)mMultiSelectActionBarView.findViewById(R.id.selected_conv_count);
         }
         getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
                 ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME |
                 ActionBar.DISPLAY_SHOW_TITLE);
         getActionBar().setCustomView(mMultiSelectActionBarView);
         ((TextView)mMultiSelectActionBarView.findViewById(R.id.title)).setText(R.string.select_item);
     }
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
         getMenuInflater().inflate(R.menu.multi_select_menu, menu);
         return true ;
     }
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
         MenuItem mItem = menu.findItem(R.id.action_slelect);
         if (mListView.getCheckedItemCount() == mAdapter.getCount()){
             mItem.setTitle(R.string.action_deselect_all);
         } else {
             mItem.setTitle(R.string.action_select_all);
         }
         return super .onPrepareOptionsMenu(menu);
     }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
         case R.id.action_slelect:
             if (mListView.getCheckedItemCount() == mAdapter.getCount()){
                 unSelectedAll();
             } else {
                 selectedAll();
             }
             mAdapter.notifyDataSetChanged();
             break ;
         default :
             break ;
         }
         return super .onOptionsItemSelected(item);
     }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
     public void selectedAll(){
         for (int i= 0; i< mAdapter.getCount(); i++){
             mListView.setItemChecked(i, true );
         }
         updateSeletedCount();
     }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
     public void unSelectedAll(){
         mListView.clearChoices();
         updateSeletedCount();
     }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
     public void updateSeletedCount(){
         mSelectedCount.setText(Integer.toString(mListView.getCheckedItemCount()));
     }
}


代码解释:


首先设置ListView模式:


1
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);


定义一个adapter,当ListView的某个item被选中之后,将该Item的背景设置为蓝色,以标记为选中。不然虽然ListView知道该item被选中,但是界面上没表现出来。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
......
     public View getView(int position, View convertView, ViewGroup parent) {
         TextView tv;
         if (convertView == null ) {
             tv = (TextView) LayoutInflater.from(mContext).inflate(
                     android.R.layout.simple_expandable_list_item_1, parent,
                     false );
         } else {
             tv = (TextView) convertView;
         }
         tv.setText(mStrings[position]);
         updateBackground(position , tv);
         return tv;
     }
     @SuppressLint( "NewApi" )
     public void updateBackground(int position, View view) {
         int backgroundId;
         if (mListView.isItemChecked(position)) {
             backgroundId = R.drawable.list_selected_holo_light;
         } else {
             backgroundId = R.drawable.conversation_item_background_read;
         }
         Drawable background = mContext.getResources().getDrawable(backgroundId);
         view.setBackground(background);
     }
......


在item每被点击一次中通知adapter,这样做的目的是为了让更新Ui以显示最新的选中状态。


1
2
3
4
5
6
7
mListView.setOnItemClickListener( new OnItemClickListener() {
     public void onItemClick(AdapterView<?> parent, View view, int position,
             long id) {
         mAdapter.notifyDataSetChanged();
         updateSeletedCount();
     }
});


其中mSelectedCount()作用是在actionbar中更新选中的数目。


1
2
3
public void updateSeletedCount(){
        mSelectedCount.setText(Integer.toString(mListView.getCheckedItemCount()));
    }


上面的代码实现了多选操作,但是在我选中一个item的时候,listView的onItemClick也同时触发,而一个ListView点击item的后续操作一般是切换到另外一个界面,所以实际应用中,我们还需要设置一个标志位,用来区别当前是多选状态还是普通状态 ,如果是多选状态,调用ListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);  如果是普通状态调用mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); CHOICE_MODE_MULTIPLE模式的特点在于他本身没有排斥性,在能选择item的情况下,也可以响应普通点击事件。为了解决这个问题 ,在android3.0之后增加了CHOICE_MODE_MULTIPLE_MODAL模式。


二、使用ListViiewCHOICE_MODE_MULTIPLE模式

CHOICE_MODE_MULTIPLE_MODAL和CHOICE_MODE_MULTIPLE恰恰相反,他是对普通点击操作和多选操作是排斥的,一旦有一个item被选中,即进入到多选状态,item的onclick事件被屏蔽。这种排斥性也是他比CHOICE_MODE_MULTIPLE多了个MODAL的原因。此外CHOICE_MODE_MULTIPLE_MODAL还结合了android3.0的actionmode,当进入多选状态,actionbar的位置会显示新的菜单。

我们来看看CHOICE_MODE_MULTIPLE_MODAL模式的实现原理:


如何实现两种状态的互斥:当点击一个item的时候absListView中会调用performItemClick,如果是CHOICE_MODE_MULTIPLE,则该item点击一次,mCheckStates中相应位置的状态变更一次,但是CHOICE_MODE_MULTIPLE_MODAL模式不同,必须要mChoiceActionMode!= null

的情况下,才会去变更mCheckStates中相应位置的状态;不光如此,如果mChoiceActionMode!= null

,他还会阻挡ItemClick事件的继续传播,从而屏蔽了ListView OnItemClickListener的onItemClick方法。


如何启用actionmode:一般我们使用actionmode都是在activity中调用startActionMode,但是如果你要使用ListView的CHOICE_MODE_MULTIPLE_MODAL,请不要这么做, 在absListView中有一个变量mChoiceActionMode,定义如下:


1
ActionMode mChoiceActionMode;


当长按item 或者是调用主动调用setItemChecked方法mChoiceActionMode将被实例化,而如果你是在activity中调用startActionMode,那么虽然actionbar上的菜单变化了,ListView 中的mChoiceActionMode却没有实例化,刚刚我们谈到mChoiceActionMode==null 表示未进入到多选状态,所以这时你点击一个item其实还是普通的点击行为。

因此在CHOICE_MODE_MULTIPLE_MODAL模式下要启用多选操作,只有两种办法:

(1)长按当长按item ;

(2)主动调用ListView的setItemChecked(int position, boolean value)方法选中一个item。

但是这两种进入多选状态的方法都有一个弊端,那就是进入多选状态之后,总是有一个item是被选中的, 方法(1)中长按item,被按的item被选中,这种结果是合理的可以接受的,但是如果你想主动进入多选状态(比如我在点击actionbar的某个菜单的时候想进入多选状态),就必须采用方法(2):调用setItemChecked,这就出现个问题,你该让哪个item被选中呢?貌似最合理的该是一个都不选中吧,我只是进入到这个状态,还没有开始选呢。幸运的是,我们可以使用一些技巧,实现能主动进入多选状态,且没有一个item被选中。

思路是我们先让第一个item被选中,这样Listview就进入多选状态,然后我们再清除被选中item的状态,代码如下:


1
2
3
4
if (item.getItemId() == R.id.action_choice){
      mListView.setItemChecked(0, true );
      mListView.clearChoices();
}


有些人可能会问,按照上面的思路,为什么不这样实现呢:


1
2
3
4
5
if (item.getItemId() == R.id.action_choice){
                                                                                                                                                                                                                                                                                                                                                                         
      mListView.setItemChecked(0, true );
      mListView.setItemChecked(0, false );
}


嘿嘿,刚刚我们提到ListView CHOICE_MODE_MULTIPLE_MODAL模式中,一旦有一个item被选中,即进入到多选状态,而他还有个相反的特性,一旦所有的Item被主动的设置为未选中,则退出多选状态,mChoiceActionMode会调用自己的finish()方法。为什么呢?在MultiChoiceModeWrapper类中:

1
2
3
4
5
6
7
8
9
@Override
public void onItemCheckedStateChanged(ActionMode mode,
         int position, long id, boolean checked) {
     mWrapped.onItemCheckedStateChanged(mode, position, id, checked);
     // If there are no items selected we no longer need the selection mode.
     if (getCheckedItemCount() == 0) {
         mode.finish();
     }
}


好了我们来实现一个CHOICE_MODE_MULTIPLE_MODAL模式下的多选操作:


代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package com.example.listmultichoise;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ChoiceModeMultipleModalActivity extends Activity {
     ListView mListView = null ;
     MyListAdapter mAdapter;
     ModeCallback mCallback;
                                                                                                                        
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_list);
                                                                                                                            
         mListView = (ListView)findViewById(R.id.list);
         mAdapter = new MyListAdapter( this ,mListView);
         mListView.setAdapter(mAdapter);
                                                                                                                            
         mCallback = new ModeCallback();
         mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
         mListView.setMultiChoiceModeListener(mCallback);
         mListView.setOnItemClickListener( new OnItemClickListener() {
             public void onItemClick(AdapterView<?> parent, View view, int position,
                     long id) {
                    Toast.makeText(ChoiceModeMultipleModalActivity. this , "选择了一个item" , 300).show();
             }
         });
     }
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         // Inflate the menu; this adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.main, menu);
         return true ;
     }
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (item.getItemId() == R.id.action_choice){
             //这里使用了一点技巧来实现处于选中状态 但是0个item 被选择
             mListView.setItemChecked(0, true );
             mListView.clearChoices();
             mCallback.updateSeletedCount();
         }
         return super .onOptionsItemSelected(item);
     }
                                                                                                                        
     private class ModeCallback implements ListView.MultiChoiceModeListener {
         private View mMultiSelectActionBarView;
         private TextView mSelectedCount;
         @Override
         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
             // actionmode的菜单处理
             MenuInflater inflater = getMenuInflater();
             inflater.inflate(R.menu.multi_select_menu, menu);
             if (mMultiSelectActionBarView == null ) {
                 mMultiSelectActionBarView = LayoutInflater.from(ChoiceModeMultipleModalActivity. this )
                     .inflate(R.layout.list_multi_select_actionbar, null );
                 mSelectedCount =
                     (TextView)mMultiSelectActionBarView.findViewById(R.id.selected_conv_count);
             }
             mode.setCustomView(mMultiSelectActionBarView);
             ((TextView)mMultiSelectActionBarView.findViewById(R.id.title)).setText(R.string.select_item);
             return true ;
         }
         @Override
         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
             if (mMultiSelectActionBarView == null ) {
                 ViewGroup v = (ViewGroup)LayoutInflater.from(ChoiceModeMultipleModalActivity. this )
                     .inflate(R.layout.list_multi_select_actionbar, null );
                 mode.setCustomView(v);
                 mSelectedCount = (TextView)v.findViewById(R.id.selected_conv_count);
             }        
             //更新菜单的状态
             MenuItem mItem = menu.findItem(R.id.action_slelect);
             if (mListView.getCheckedItemCount() == mAdapter.getCount()){
                 mItem.setTitle(R.string.action_deselect_all);
             } else {
                 mItem.setTitle(R.string.action_select_all);
             }
             return true ;
         }
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
             switch (item.getItemId()) {
                 case R.id.action_slelect:
                     if (mListView.getCheckedItemCount() == mAdapter.getCount()){
                         unSelectedAll();
                     } else {
                         selectedAll();
                     }
                     mAdapter.notifyDataSetChanged();
                     break ;
                 default :
                     break ;
             }
             return true ;
         }
         @Override
         public void onDestroyActionMode(ActionMode mode) {
             mListView.clearChoices();
         }
         @Override
         public void onItemCheckedStateChanged(ActionMode mode,
                 int position, long id, boolean checked) {
             updateSeletedCount();
             mode.invalidate();
             mAdapter.notifyDataSetChanged();
         }
                                                                                                                            
         public void updateSeletedCount(){
             mSelectedCount.setText(Integer.toString(mListView.getCheckedItemCount()));
         }
     }
     public void selectedAll(){
         for (int i= 0; i< mAdapter.getCount(); i++){
             mListView.setItemChecked(i, true );
         }
         mCallback.updateSeletedCount();
     }
                                                                                                                        
     public void unSelectedAll(){
         mListView.clearChoices();
         mListView.setItemChecked(0, false );
         mCallback.updateSeletedCount();
     }
}

这里需要提醒的是虽然ListView的mActionMode我们不能直接操作,但是actionmode的回调方法是可以在activity中设置的:

1
mListView.setMultiChoiceModeListener(mCallback);

而且这个回调方法比一般的actionmode回调方法多了个onItemCheckedStateChanged

1
2
3
4
5
@Override
public void onItemCheckedStateChanged(ActionMode mode,
         int position, long id, boolean checked) {
     ....
}


demo我已经上传到了csdn:http://download.csdn.net/detail/jianghejie123/8126071


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值