好记性不如铅笔头

android, 编程

Android应用开发笔记:Listview的使用汇总

android Listview是一个非常常用的控件,这里备份下它的各种使用方式。

github:

https://github.com/cstriker1407/android/tree/master/HelloListView 】

CONTENTS

最基本的使用

java代码:

public class Activity1 extends Activity
{
	private List<String> dataList;
	private ArrayList<HashMap<String, String>> mylist;
	
	private ListView listView1;
	private ListView listView2;
	private ArrayAdapter<String> adapter2;
	private SimpleAdapter mSchedule;
	private int idx = 0;
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity1);
		
	    //绑定XML中的ListView,作为Item的容器  
	    listView1 = (ListView) findViewById(R.id.listView1);  
	      
	    //生成动态数组,并且转载数据  
	    mylist = new ArrayList<HashMap<String, String>>();  
	    for(int i=0;i<20;i++)  
	    {  
	        HashMap<String, String> map = new HashMap<String, String>();  
	        map.put("ItemTitle", "This is Title....." + i);  
	        map.put("ItemText", "This is text.....");  
	        mylist.add(map);
	    }  
	    //生成适配器,数组===》ListItem  
	    mSchedule = new SimpleAdapter(this, //没什么解释  
	                                                mylist,//数据来源   
	                                                R.layout.my_listitem,//ListItem的XML实现  
	                                                //动态数组与ListItem对应的子项          
	                                                new String[] {"ItemTitle", "ItemText"},   
	                                                //ListItem的XML文件里面的两个TextView ID  
	                                                new int[] {R.id.ItemTitle,R.id.ItemText});  
	    //添加并且显示  
	    listView1.setAdapter(mSchedule);  

	    dataList = new ArrayList<String>();
	    for (int i = 0; i < 20; i++)
		{
	    	dataList.add("test " + idx++ );
		}
	    
	    listView2 = (ListView)findViewById(R.id.listView2);
        Button headButton = new Button(this);
        listView2.addHeaderView(headButton);
        adapter2 = new ArrayAdapter<String>(this, R.layout.my_listitem, R.id.ItemTitle, dataList);
        listView2.setAdapter(adapter2);
	    
        ((Button)findViewById(R.id.button1)).setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
			    for(int i=20;i<25;i++)  
			    {  
			        HashMap<String, String> map = new HashMap<String, String>();  
			        map.put("ItemTitle", "This is Title....." + i);  
			        map.put("ItemText", "This is text.....");  
			        mylist.add(map);
			    } 
			    mSchedule.notifyDataSetChanged();
				
			    for (int i = 0; i < 5; i++)
				{
			    	dataList.add("test " + idx++);
				}
			    adapter2.notifyDataSetChanged();
			}
		});
	}
}

my_listitem.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/MyListItem"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingBottom="3dip"
    android:paddingLeft="10dip" >
    <TextView
        android:id="@+id/ItemTitle"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="30dip" >
    </TextView>
    <TextView
        android:id="@+id/ItemText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </TextView>
</LinearLayout>

 备注:

代码写的比较乱,这里简单总结下:

1)简单的listview的adapter可以使用SimpleAdapter或ArrayAdapter来实现,通过传入自定义layout的id,可以方便的使用自定义layout。

2)在设置完数据之后,我们仍然可以通过修改数据源,然后调用adapter的 notifyDataSetChanged() 方法来刷新页面。

3)可以通过 addHeadView 和 addFooterView 方法来为listview添加上下的view。

使用SimpleCursorAdapter

java代码:

ListView listView1 = (ListView)findViewById(R.id.listView1);

Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
startManagingCursor(cursor);
ListAdapter listAdapter = new SimpleCursorAdapter(this, R.layout.my_listitem, 
            cursor,
            new String[]{People.NAME}, 
            new int[]{R.id.ItemTitle});
listView1.setAdapter(listAdapter);

listView1.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
	public void onItemClick(AdapterView<?> parent, View view, int position, long id)
	{
		Toast.makeText(Activity2.this, "position:" + position, Toast.LENGTH_SHORT).show();
	}
});

 备注:

1)cursoradapter有一些使用注意事项,后续备忘。

2)可以通过设置listview的 setOnItemClickListener 方法来实现简单的单击相应。

使用自定义的apdater:

java代码:

ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();  
for(int i=0;i<20;i++)  
{  
    HashMap<String, String> map = new HashMap<String, String>();  
    map.put("ItemTitle", "This is Title....." + i);  
    map.put("ItemText", "This is text.....");  
    mylist.add(map);
}
ListView listView2 = (ListView)findViewById(R.id.listView2);
listView2.setAdapter(new Activity2Adapter(this, mylist));
class Activity2Adapter extends BaseAdapter
{
	class ViewHolder
	{
		public TextView title;
		public TextView info;
	}

	private LayoutInflater mInflater;
	private ArrayList<HashMap<String, String>> mylist;
	
	public Activity2Adapter(Context context, ArrayList<HashMap<String, String>> mylist)
	{
		this.mInflater = LayoutInflater.from(context);
		this.mylist = mylist;
	}
	@Override
	public int getCount() 
	{
		return mylist.size();
	}

	@Override
	public Object getItem(int arg0) {
		return null;
	}

	@Override
	public long getItemId(int arg0) {
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		
		ViewHolder holder = null;
		if (convertView == null) 
		{
			holder=new ViewHolder();  
			convertView = mInflater.inflate(R.layout.my_listitem, null);
			holder.title = (TextView)convertView.findViewById(R.id.ItemTitle);
			holder.info = (TextView)convertView.findViewById(R.id.ItemText);
			convertView.setTag(holder);
		}else 
		{
			holder = (ViewHolder)convertView.getTag();
		}

		holder.title.setText((String)mylist.get(position).get("ItemTitle"));
		holder.info.setText((String)mylist.get(position).get("ItemText"));
		return convertView;
	}
}

 备注:

1)使用自定义的adapter有非常多的实例,而且istview的使用基本上都是使用自定义的adapter。

2)关于adapter的各个方法的实现,这里只实现了最简单的几个。其他的具体需求可以参考sdk。

分组listview:

java代码:

public class Activity3 extends Activity
{
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity3);
		
	    List<Map<String, String>> mylist = new ArrayList<Map<String, String>>();  
	    List<Map<String, String>> splitList = new ArrayList<Map<String, String>>(); 
        // 组织数据源  
        Map<String, String> mp = new HashMap<String, String>();  
        mp.put("itemTitle", "A");  
        mylist.add(mp);  
        splitList.add(mp);  
  
        for (int i = 0; i < 3; i++) {  
            Map<String, String> map = new HashMap<String, String>();  
            map.put("itemTitle", "文章1-" + i);  
            mylist.add(map);  
        }  
  
        mp = new HashMap<String, String>();  
        mp.put("itemTitle", "B");  
        mylist.add(mp);  
        splitList.add(mp);
  
        for (int i = 0; i < 6; i++) {  
            Map<String, String> map = new HashMap<String, String>();  
            map.put("itemTitle", "文章2-" + i);  
            mylist.add(map);  
        }  
        ListView listView1 = (ListView) findViewById(R.id.listView1);  
        listView1.setAdapter(new Activity3Adapter(this, mylist, splitList));
	}
}
class Activity3Adapter extends BaseAdapter {  
	  
    private LayoutInflater mInflater;  
  
    private List<Map<String, String>> listData;  
  
    private List<Map<String, String>> splitData;  
  
    public Activity3Adapter(Context context,  
            List<Map<String, String>> listData,  
            List<Map<String, String>> splitData) {  
        this.mInflater = LayoutInflater.from(context);  
        this.listData = listData;  
        this.splitData = splitData;  
    }  
  
    @Override  
    public int getCount() {  
        return listData.size();  
    }  
  
    @Override  
    public Object getItem(int position) {  
        return listData.get(position);  
    }  
  
    @Override  
    public long getItemId(int position) {  
        return position;  
    }  
  
    @Override  
    public boolean isEnabled(int position) {  
        if (splitData.contains(listData.get(position))) {  
            return false;  
        }  
        return super.isEnabled(position);  
    }  
  
    @Override  
    public View getView(final int position, View convertView, ViewGroup parent) {  
        if (splitData.contains(listData.get(position))) {  
            convertView = mInflater.inflate(R.layout.my_listitem_tag, null);  
        } else {  
            convertView = mInflater.inflate(R.layout.my_listitem, null);  
        }  
  
        TextView textView = (TextView) convertView.findViewById(R.id.ItemTitle);  
        textView.setText(listData.get(position).get("itemTitle"));  
  
        return convertView;  
    }  
}  

 备注:

1)通过分析代码可以发现,实现这种listview的核心在于通过重写 getView 方法,根据当前的位置ID来生成不同的view。

可伸缩扩展ListView:

java文件:

public class Activity4 extends Activity
{
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity4);
		
	    ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();  
	    for(int i=0;i<20;i++)  
	    {  
	        HashMap<String, String> map = new HashMap<String, String>();  
	        map.put("ItemTitle", "This is Title....." + i);  
	        map.put("ItemText", "This is text....." + i);  
	        map.put("visible","1");  
	        mylist.add(map);
	    }
	    ListView listView2 = (ListView)findViewById(R.id.listView1);
	    listView2.setAdapter(new Activity4Adapter(this, mylist));
	    
	    listView2.setOnItemClickListener(new AdapterView.OnItemClickListener()
		{
	    	public void onItemClick(AdapterView<?> parent, View view, int position, long id)
	    	{
	    		if( "1".equals(((Activity4Adapter)parent.getAdapter()).mylist.get(position).get("visible")) )
	    		{
	    			((Activity4Adapter)parent.getAdapter()).mylist.get(position).put("visible", "0");
	    		}else
	    		{
	    			((Activity4Adapter)parent.getAdapter()).mylist.get(position).put("visible", "1");
	    		}
	    		
	    		((Activity4Adapter)parent.getAdapter()).notifyDataSetChanged();
	    	}
		});
	    
	}
}
class ViewHolder
{
	public TextView title;
	public TextView info;
}
class Activity4Adapter extends BaseAdapter
{
	private LayoutInflater mInflater;
	public ArrayList<HashMap<String, String>> mylist;
	
	public Activity4Adapter(Context context, ArrayList<HashMap<String, String>> mylist)
	{
		this.mInflater = LayoutInflater.from(context);
		this.mylist = mylist;
	}
	@Override
	public int getCount() 
	{
		return mylist.size();
	}

	@Override
	public Object getItem(int arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) 
	{
		ViewHolder holder = null;
		if (convertView == null) 
		{
			holder=new ViewHolder();  
			convertView = mInflater.inflate(R.layout.my_listitem, null);
			holder.title = (TextView)convertView.findViewById(R.id.ItemTitle);
			holder.info = (TextView)convertView.findViewById(R.id.ItemText);
			convertView.setTag(holder);
			
		}else 
		{
			holder = (ViewHolder)convertView.getTag();
		}

		holder.title.setText((String)mylist.get(position).get("ItemTitle"));
		holder.info.setText((String)mylist.get(position).get("ItemText"));
		
		if("1".equals((String)mylist.get(position).get("visible")))
		{
			holder.info.setVisibility(View.VISIBLE);
		}else 
		{
			holder.info.setVisibility(View.GONE);
		}
		return convertView;
	}
}

备注:

1)代码写的比较绕,主要是想尝试下listview的各种方法。

2)通过分析代码,该需求的实现很简单:接收到单击相应的view设置自己的子view的显示模式(VISIBLE 或者 GONE),然后通知页面刷新;在getview的实现方法中加以处理,防止上下刷新后页面混乱。

单选多选Listview

java文件:

String[] GENRES = new String[] {
      "Action", "Adventure", "Animation", "Children", "Comedy", "Documentary", "Drama",
      "Foreign", "History", "Independent", "Romance", "Sci-Fi", "Television", "Thriller"
  };
ListView listView1 = (ListView)findViewById(R.id.listView1);
listView1.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_single_choice, GENRES));
listView1.setItemsCanFocus(false);
listView1.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

ListView listView2 = (ListView)findViewById(R.id.listView2);
listView2.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_multiple_choice, GENRES));
listView2.setItemsCanFocus(false);
listView2.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

 备注:

1)demo代码只是实现了最简单的单选多选,实际应用中单选多选往往很复杂,一般会用自定义的layout来实现。

ExpandableListView:

java代码:

public class Activity6 extends Activity
{
    private static final String NAME = "NAME";
    private static final String IS_EVEN = "IS_EVEN";
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity6);

		ExpandableListView expandableListView1 = (ExpandableListView) findViewById(R.id.expandableListView1);
		
		/* 父级的数据list,每个元素是一个hashmap */
        List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
        
        /* 子类数据list,每个元素也是一个list,这个list是这个子链表的元素集合。 */
        List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();
        for (int i = 0; i < 20; i++) {
            Map<String, String> curGroupMap = new HashMap<String, String>();
            groupData.add(curGroupMap);
            curGroupMap.put(NAME, "Group " + i);
            curGroupMap.put(IS_EVEN, (i % 2 == 0) ? "This group is even" : "This group is odd");
            
            List<Map<String, String>> children = new ArrayList<Map<String, String>>();
            for (int j = 0; j < 15; j++) {
                Map<String, String> curChildMap = new HashMap<String, String>();
                children.add(curChildMap);
                curChildMap.put(NAME, "Child " + j);
                curChildMap.put(IS_EVEN, (j % 2 == 0) ? "This child is even" : "This child is odd");
            }
            childData.add(children);
        }
		
        expandableListView1.setAdapter(
        		new SimpleExpandableListAdapter(
                this,
                groupData,
                android.R.layout.simple_expandable_list_item_1,
                new String[] { NAME, IS_EVEN },
                new int[] { android.R.id.text1, android.R.id.text2 },
                childData,
                android.R.layout.simple_expandable_list_item_2,
                new String[] { NAME, IS_EVEN },
                new int[] { android.R.id.text1, android.R.id.text2 }
                ));
        
		ExpandableListView expandableListView2 = (ExpandableListView) findViewById(R.id.expandableListView2);
		expandableListView2.setAdapter(new MyExpandableListAdapter());
		expandableListView2.expandGroup(0);//设置第一组张开
		expandableListView2.setGroupIndicator(null);//除去自带的箭头
		
		
	}

	class MyExpandableListAdapter extends BaseExpandableListAdapter {
	    // Sample data set.  children[i] contains the children (String[]) for groups[i].
	    private String[] groups = { "People Names", "Dog Names", "Cat Names", "Fish Names" };
	    private String[][] children = {
	            { "Arnold", "Barry", "Chuck", "David" },
	            { "Ace", "Bandit", "Cha-Cha", "Deuce" },
	            { "Fluffy", "Snuggles" },
	            { "Goldy", "Bubbles" }
	    };
	    
	    public Object getChild(int groupPosition, int childPosition) {
	        return children[groupPosition][childPosition];
	    }

	    public long getChildId(int groupPosition, int childPosition) {
	        return childPosition;
	    }

	    public int getChildrenCount(int groupPosition) {
	        return children[groupPosition].length;
	    }

	    public TextView getGenericView() {
	        // Layout parameters for the ExpandableListView
	        AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
	                ViewGroup.LayoutParams.MATCH_PARENT, 64);

	        TextView textView = new TextView(Activity6.this);
	        textView.setLayoutParams(lp);
	        // Center the text vertically
	        textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
	        // Set the text starting position
	        textView.setPadding(36, 0, 0, 0);
	        return textView;
	    }
	    
	    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
	            View convertView, ViewGroup parent) {
	        TextView textView = getGenericView();
	        textView.setText(getChild(groupPosition, childPosition).toString());
	        return textView;
	    }

	    public Object getGroup(int groupPosition) {
	        return groups[groupPosition];
	    }

	    public int getGroupCount() {
	        return groups.length;
	    }

	    public long getGroupId(int groupPosition) {
	        return groupPosition;
	    }

	    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
	            ViewGroup parent) {
	        TextView textView = getGenericView();
	        textView.setText(getGroup(groupPosition).toString());
	        return textView;
	    }

	    public boolean isChildSelectable(int groupPosition, int childPosition) {
	        return true;
	    }

	    public boolean hasStableIds() {
	        return true;
	    }
	}
}

备注:

1)ExpandableListView是一个可以内嵌listview的listview。demo里面包含两种实现方式,都比较简略。如果要实际应用,需要查询SDK。

XListView-Android-master的使用:

XListView是一个非常简单好用的可以支持上拉,下拉Listview的开源库。

github:

https://github.com/Maxwin-z/XListView-Android 】

使用方法:

1)将开源库demo中【 me.maxwin.view 】包下的三个java文件【 XListView.java 】【 XListViewHeader.java 】【 XListViewFooter.java 】拷贝到项目工程里。

2)将开源库demo中【 res/drawable-hdpi 】文件夹下的【 xlistview_arrow.png 】拷贝到项目工程相同路径下。

3)将开源库demo中【 res/layout 】文件夹下的【 xlistview_footer.xml 】【 xlistview_header.xml 】拷贝到项目工程相同路径下。

4)将开源库demo中【 values 】文件夹下的【 strings.xml 】合并到项目工程相同文件下。

java文件:

public class Activity7 extends Activity
{
	private XListView mListView;
	private ArrayAdapter<String> mAdapter;
	
	private ArrayList<String> items = new ArrayList<String>();
	private int start = 0;
	private void geneItems() {
		for (int i = 0; i != 20; ++i) {
			items.add("refresh cnt " + (++start));
		}
	}
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity7);
		
		mListView = (XListView) findViewById(R.id.xListView1);
		mListView.setPullLoadEnable(true);
		mAdapter = new ArrayAdapter<String>(this, R.layout.list_item, items);
		mListView.setAdapter(mAdapter);
//		mListView.setPullLoadEnable(false);
//		mListView.setPullRefreshEnable(false);
		mListView.setXListViewListener(new IXListViewListener()
		{
			@Override
			public void onRefresh()
			{
				geneItems();
				mAdapter.notifyDataSetChanged();
				mListView.stopRefresh();
				mListView.stopLoadMore();
				mListView.setRefreshTime("刚刚");
			}
			
			@Override
			public void onLoadMore()
			{
				geneItems();
				mAdapter.notifyDataSetChanged();
				mListView.stopRefresh();
				mListView.stopLoadMore();
				mListView.setRefreshTime("刚刚");
			}
		});
	}
}

 XML文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <me.maxwin.view.XListView
        android:id="@+id/xListView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </me.maxwin.view.XListView>
</LinearLayout>

 备注:

1)xlistview的代码写的非常简洁,可以非常容易进行扩充和修改,很多项目都在使用它。

Android-PullToRefresh的使用:

android-pulltorefresh是另外一个非常好用的支持上拉,下拉Listview的开源库。android-pulltorefresh的代码分为3个部分,写的比Xlistview要多多了。

github:

https://github.com/chrisbanes/Android-PullToRefresh 】

使用方法:

和使用其他的开源库一样,将pulltorefresh下载下来,连接到项目工程中,就可以使用了。

java文件:

public class Activity8 extends Activity
{
	private ArrayList<String> mListItems;
	private ArrayAdapter<String> mAdapter;
	private PullToRefreshListView pullToRefreshView;
	private int idx = 0;
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity8);
		
		mListItems = new ArrayList<String>();
		for (int i = 0; i < 10; i++)
		{
			mListItems.add("string" + idx++);
		}
		
		mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);
		pullToRefreshView = (PullToRefreshListView) findViewById(R.id.pull_to_refresh_listview);
		pullToRefreshView.setOnRefreshListener(new OnRefreshListener2<ListView>()
		{
			public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView)
			{
				for (int i = 0; i < 5; i++)
				{
					mListItems.add("Down string" + idx++);
				}
				Toast.makeText(Activity8.this, "Pull Down!", Toast.LENGTH_SHORT).show();
				new GetDataTask().execute();
			}
			public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView)
			{
				for (int i = 0; i < 5; i++)
				{
					mListItems.add("Up string" + idx++);
				}
				Toast.makeText(Activity8.this, "Pull Up!", Toast.LENGTH_SHORT).show();
				new GetDataTask().execute();
			}
		});
		pullToRefreshView.setMode(PullToRefreshBase.Mode.BOTH);
		pullToRefreshView.getRefreshableView().setAdapter(mAdapter);
		
	}
	private class GetDataTask extends AsyncTask<Void, Void, String[]> {

		@Override
		protected String[] doInBackground(Void... params) {
			// Simulates a background job.
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
			return null;
		}
		@Override
		protected void onPostExecute(String[] result) {
			// Call onRefreshComplete when the list has been refreshed.
			pullToRefreshView.onRefreshComplete();

			super.onPostExecute(result);
		}
	}
}

 XML文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <com.handmark.pulltorefresh.library.PullToRefreshListView
        android:id="@+id/pull_to_refresh_listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

备注:

1)如果要同时支持上拉,下拉操作,需要显示的调用 setMode 方法。

备注:

1)android的listview是一个使用非常广泛的控件,网上有各种使用方法。这里简单备份下一些常见的方法。

2)上述demo很多都简化了大量的业务操作,如果要实际应用,需要查询下sdk。以后补上更详细的demo。

3)参考【 http://www.cnblogs.com/allin/archive/2010/05/11/1732200.html 】【 http://blog.csdn.net/hellogv/article/details/4542668 】【 http://iaiai.iteye.com/blog/1188668 】

发表评论

4 × 4 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据