第三章UI
一、常用控件
1、TextView
2、Button
3、EditText
密碼:android:password=”true”
4、ImageView
5、ProgressBar
設置其進度
progress=bar.getProgress();
progress+=10;
bar.setProgress(progress);
if(progress==100)
{
bar.setVisibility(View.GONE);
}
6、AlertDialog
AlertDialog.Builder dialog=new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("確認刪除");
dialog.setMessage("你確認刪除么?");
dialog.setCancelable(false);
dialog.setPositiveButton("確認", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "已經刪除", Toast.LENGTH_SHORT).show();
}
});
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "已經取消", Toast.LENGTH_SHORT).show();
}
});
dialog.show();
7、ProgressDialog
和AlertDialog類似,只是內容為一個進度條。
進度加載完成之后,必須使用dismiss()來關閉對話框。
二、基本布局
1、LinearLayout
android:gravity指定文字在控件中的對齊方式
android:layout_gravity:指定控件在布局中的對齊方式
android:layout_weight:按比例分配控件大小
2、RelativeLayout
3、FrameLayout
4、TableLayout
android:layout_span=”2”將兩列合并為一列
在TableRow中無法指定控件的寬度,通過android:stretchColumns=”1”,指定將第二列拉伸到最大。
5、GridLayout
三、自定義控件
Android中,控件和布局的繼承結構圖
1、添加自定義標題布局
自定義一個布局title.xml,然后在mainactivity布局中引入
當然,需要將系統自帶標題欄屏蔽
requestWindowFeature(Window.FEATURE_NO_TITLE);
2、創建自定義控件
上面方法自定義的標題欄并不能響應操作,采用自定義控件方法來實現操作。
(1)首先,構建一個title.xml布局文件
(2)然后,構建一個自定義標題控件TitleLayout:
利用LayoutInflater動態加載布局文件title.xml。
public class TitleLayout extends LinearLayout{
public TitleLayout( Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title, this);
Button edit=(Button) findViewById(R.id.title_edit);
Button back=(Button) findViewById(R.id.title_back);
edit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getContext(), "Edit", Toast.LENGTH_SHORT).show();
}
});
back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getContext(), "Back", Toast.LENGTH_SHORT).show();
}
});
}
}
(3)如同加入其它的控件一樣,將該自定義的控件添加到mainactivity.xml文件中
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
四、ListView
1、最簡單的Adapter
要將數據放置在ListView中,都需要一個adapter轉換。
一個最簡單的adapter,就是把一個字符串數組放置在ListView中。
ArrayAdapter接收3個參數:context,ListView單個子項布局id和數據。
listView=(ListView) findViewById(R.id.listView1);
ArrayAdapter adapter=new ArrayAdapter(MainActivity.this,
android.R.layout.simple_list_item_1, data);
listView.setAdapter(adapter);
2、定制ListView界面
只顯示文字很單調,需要顯示圖片等,則需要構建自定義的布局。
(1)數據:Fruit類
首先準備需要適配的數據,數據包括文字、圖片id,定義一個Fruit類存放這些數據。
(2)子項布局:fruit_layout.xml
之后,需要自定義ListView中單個子項的布局。本例中就是一個圖片加上一個文字。
(3)自定義適配器:FruitAdapter.java
該適配器中,最重要的是getView()方法。該方法在每個子項滾動到屏幕內時被調用。
position是該子項的位置,利用getItem(position)可以獲得當前的Fruit實例fruit;
然后,利用LayoutInflater可以加載布局為fruit_layout的布局view;
該布局view即為步驟(2)中自定義的布局,通過view.findViewById()可以獲得ImageView和TextView。
最后,將fruit中的imageId和name傳入ImageView和TextView。
public class FruitAdapter extends ArrayAdapter{
private int resourceId;
public FruitAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
resourceId=resource;
}
public View getView(int position, View convertView, ViewGroup parent) {
Fruit fruit=getItem(position);
View view=LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, null);
TextView fruit_name=(TextView) view.findViewById(R.id.fruit_name);
ImageView fruit_image=(ImageView) view.findViewById(R.id.fruit_image);
fruit_image.setImageResource(fruit.getImageId());
fruit_name.setText(fruit.getName());
return view;
}
}
(4)使用
List fruits=new ArrayList();
FruitAdapter adapter=new FruitAdapter(MainActivity.this, R.layout.fruit_layout, fruits);
在fruits中添加數據。
3、提升ListView效率
getView()每次都將布局重新加載一遍,效率很低。處理方法為:
(1)convertView
convertView將之前加載好的布局進行緩存,以便之后重用。則可以不必每次都使用LayoutInflater重新加載布局,而直接加載緩存的布局。
if(convertView==null) view=LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, null);
else
view=convertView;
(2)ViewHolder
每次都使用findViewById獲取控件,效率低下。
使用convertView將之前已經find的view也一起緩存。
View有setTag()和getTag()方法,分別進行數據寫入和讀取。
采用自定義的ViewHolder類,將多個參數一起管理,比如TextView/ImageView等。
public class FruitAdapter extends ArrayAdapter {
public FruitAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
resourceId = resource;
}
private int resourceId;
public View getView(int position, View convertView, ViewGroup parent) {
Fruit fruit = getItem(position);
View view;
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder(); ??//一定要記住實例化對象啊
view = LayoutInflater.from(getContext()).inflate(
R.layout.fruit_layout, null);
viewHolder.fruit_image = (ImageView) view
.findViewById(R.id.fruit_image);
viewHolder.fruit_name=(TextView) view.findViewById(R.id.fruit_name);
view.setTag(viewHolder);
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.fruit_image.setImageResource(fruit.getImageId());
viewHolder.fruit_name.setText(fruit.getName());
return view;
}
class ViewHolder {
ImageView fruit_image;
TextView fruit_name;
}
}
4、ListView點擊事件
注冊setOnItemClickListener()事件:
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View view,
int position, long id) {
Fruit fruit=fruits.get(position);
Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
五、單位和尺寸
px:像素
pt:磅數,1pt=1/72inch
dp:密度無關像素
密度dpi:屏幕每inch包含的像素數。
獲取當前屏幕密度值:
float xdpi=getResources().getDisplayMetrics().xdpi;
float ydpi=getResources().getDisplayMetrics().ydpi;
sp:可伸縮像素。
規定,在160dpi屏幕上,1dp=1px;在320dpi屏幕上,1dp=2px.
六、最佳實踐——聊天界面
APP: ChatWe
新內容有:
當有新內容時,刷新ListView中的顯示:adapter.notifyDataSetChanged();
將ListView定位到最后一行:listView.setSelection(messages.size());
指定ListView中分割線為透明:android:divider=”#0000”