文章地址:http://blog.csdn.net/scarthr/article/details/41959679
一 Android布局
五大布局:LinearLayout、RelativeLayout、FrameLayout、AbsoluteLayout、TableLayout,个人认为后面两个布局基本可以用前面的布局组合来实现,所以只是用前面的3个布局基本可以买足一切怪异、另类的布局了。从Android2.2开始,新增了MATCH_PARENT,其值和FILL_PARENT值一样都是-1。WRAP_CONTENT是-2。
二 ListView控件
要使用ListView就离不开Adapter,一个ListView要配置一个Adapter,才能正常显示数据。1. ArrayAdapter
要使用系统自带的列表项的话,如下:
ListView listView = (ListView) findViewById(R.id.lv);
ArrayAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1);
adapter.add("第一项");
adapter.add("第二项");
adapter.add("第三项");
listView.setAdapter(adapter);
要使用自己创建的列表项,先创建一个item_cell.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</TextView>
修改上述代码如下:
ListView listView = (ListView) findViewById(R.id.lv);
ArrayAdapter adapter = new ArrayAdapter<String>(this,
R.layout.item_cell);
adapter.add("第一项");
adapter.add("第二项");
adapter.add("第三项");
listView.setAdapter(adapter);
如果希望在ArrayAdapter中,存的不仅仅是String,存对象改怎么办呢?
新建User类:
package com.thr.testandroid;
public class User {
private String name;
private int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
注意要复写User的toString()方法,不然一会ListView中会显示的数据不是姓名而是一连串对象的地址名。
再次修改代码: ListView listView = (ListView)findViewById(R.id.lv);
ArrayAdapter adapter = new ArrayAdapter<User>(this, R.layout.item_cell);
adapter.add(new User("夏明", 12);
adapter.add(new User("王亮", 14);
listView.setAdapter(adapter);
要为ListView监听单击事件加入:
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
User user = adapter.getItem(position);
Toast.makeText(
MainActivity.this,
String.format("姓名: %s, 年龄: %s", user.getName(),
user.getAge()), Toast.LENGTH_SHORT).show();
}
});
2. BaseAdapter
创建MyAdapter继承BaseAdapter:
package com.thr.testandroid;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class MyAdapter extends BaseAdapter {
private Context context;
private String[] stringArray = new String[] { "1", "2", "3", "4", "5", "6",
"7", "8", "9", "10" };
public MyAdapter(Context context) {
this.context = context;
}
@Override
public int getCount() {
return stringArray.length;
}
@Override
public String getItem(int position) {
return stringArray[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(context);
tv.setText(getItem(position));
return tv;
}
}
然后设置好我们创建的MyAdapter:
MyAdapter adapter = new MyAdapter(this);
listView.setAdapter(adapter);
Done。
getCount是取得所有数据的数量,getItem(int position)用来取得指定的某一条数据,getItemId(int position)用来取得当前position位置数据的Id,getView(int position, View convertView, ViewGroup parent)是当前显示出来的那一条View,只要屏幕显示出来一条数据,getView就会执行一次。
此时有一个问题,如果这个条目如果很大很大,成千上万甚至更大那么,每次都要new TextView吗?那岂不是太浪费内存了,那么优化ListView的机制就出来了。
我们更改上面getView方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv;
if (convertView != null) {
tv = (TextView) convertView;
} else {
tv = new TextView(context);
}
tv.setText(getItem(position));
return tv;
}
这样在convertView不为空的时候就会剩下很多资源。
下来我们实现一个稍微复杂一点的ListView,带图标和文字的ListView。
首先新建item_listview.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="horizontal" >
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
创建ItemData类:
package com.thr.testandroid;
public class ItemData {
private int imageId;
private String name;
public ItemData(int imageId, String name) {
super();
this.imageId = imageId;
this.name = name;
}
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建ItemAdapter继承BaseAdapter:
package com.thr.testandroid;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ItemAdapter extends BaseAdapter {
private Context context;
private List<ItemData> itemList;
public ItemAdapter(Context context) {
this.context = context;
itemList.add(new ItemData(R.drawable.ic_launcher, "张三"));
itemList.add(new ItemData(R.drawable.ic_launcher, "李四"));
itemList.add(new ItemData(R.drawable.ic_launcher, "王五"));
}
@Override
public int getCount() {
return itemList.size();
}
@Override
public Object getItem(int position) {
return itemList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
ItemData data = itemList.get(position);
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(
R.layout.item_listview, null);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ImageView iv = (ImageView) convertView.findViewById(R.id.iv);
TextView tv = (TextView) convertView.findViewById(R.id.tv);
iv.setImageResource(data.getImageId());
tv.setText(data.getName());
return convertView;
}
class ViewHolder {
ImageView iv;
TextView tv;
}
}
这里我们创建了ViewHolder类,这是一个类持有者,他用来保存我们在getView中已经创建好的convertView,用setTag()保存好标签,在再次需要使用的时候调用getTag()便可以得到我们需要的convertView,这样既节省了内存,也使得效率更高。
在需要使用ItemAdapter的地方调用:
ItemAdapter adapter = new ItemAdapter(this);
listView.setAdapter(adapter);
在ItemAdapter的构造方法中可以修改为带数据集合参数的方法,我这里是为了方便直接写在ItemAdapter内部了。
还有一中方法可以快速创建ListView,我们可以创建一个继承自ListActivity的类MyListActivity:
package com.thr.testandroid;
import android.app.ListActivity;
import android.os.Bundle;
public class MyListActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ItemAdapter(this));
}
}
这样子就行了,是不是非常方便快捷呢?连Activity的布局都不用设置。如果需要对Activity布局做调整,则创建activity_listview.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" >
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="按钮" />
</LinearLayout>
在Activity中增加:
setContentView(R.layout.item_listview);