android基礎--ListView控制元件,android對話方塊
用ScrollVeiw+TextView方式顯示多條目列表時,會創建出所有可顯示的物件,易造成記憶體溢位。谷歌工程師給我們提供了ListView控制元件。
ListView,只需要建立(一屏能顯示出來的物件個數+1)個Item物件,再下拉顯示時,之前顯示現在完全隱藏的物件會被賦值給介面卡getView()方法的convertView引數,可以在getView()方法中反覆複用convertView物件,後面新顯示的物件都不需要再新建立物件。
ListView是典型的按MVC模式設計的。
--- M:SQLite資料庫
--- V:ListView
--- C:Adapter
ListView控制元件使用時需要為其配置資料介面卡:void setAdapter(ListAdapter adapter)。
直接繼承ListAdapter介面有很多方法要複寫,可繼承其預設實現類BaseAdapter。
---android介面預設實現類,要麼以simple開頭,要麼以default或base開頭。
BaseAdapter的2個重要方法
int getCount(),獲取要顯示在ListView中的總記錄數。
View getView(int position,View convertView,ViewGroup parent),指定ListView中的條目,從資料庫或集合指定位置獲取資料構造一個View,這個View可以new TextView(),也可以是通過View.inflat()填充出來的,還可以複用convertView。
---position就是ListView中的條目。
---convertView,接收完全隱藏起來的子條目的view物件。可複用這個convertView,不用每次都new EditView()或inflat()出新的檢視。
複用convertView()的程式碼如下:
上面程式碼中,static View inflate(Context context, int resource, ViewGroup root),是View的靜態方法,從一個xml 佈局檔案中轉換成一個View物件。public View getView(int position, View convertView, ViewGroup parent) { TextView tv = null; if(convertView == null) { System.out.println("getView 新建: " + position); // 如果convertView等於null, 沒有快取過物件, 新建一個 tv = new TextView(MainActivity.this); } else { System.out.println("getView 複用: " + position); // 如果convertView不等於null, 某個條目的物件被快取了, 拿過來直接複用 tv = (TextView) convertView; } .... } 或者 public View getView(int position, View convertView, ViewGroup parent) { View view = null; if(convertView == null) { System.out.println("新建:" + position); // 佈局填充器, 打氣筒, 功能: 把佈局檔案, 轉換成一個View物件 LayoutInflater inflater = LayoutInflater.from(MainActivity2.this); view = inflater.inflate(R.layout.listview_item, null); } else { System.out.println("複用:" + position); view = convertView; } TextView tvName = (TextView) view.findViewById(R.id.tv_listview_item_name); TextView tvAge = (TextView) view.findViewById(R.id.tv_listview_item_age); TextView tvBalance = (TextView) view.findViewById(R.id.tv_listview_item_balance); ...... }
ListView資料顯示的進一步優化,使用靜態內部類ViewHolder:
class ChatListAdapter extends BaseAdapter
{
static class ViewHolder
{
TextView text;
ImageView icon;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}
}
ViewHolder的作用:優化顯示效率,即之前顯示過的不用再從佈局檔案讀取,直接從快取中讀取。可以看到它只是一個靜態類,它的作用就在於減少不必要的呼叫findViewById。
常用現成的資料介面卡(都有侷限性,最靈活的還是BaseAdapter)
1) ArrayAdapter
是BaseAdapter的子類,內部已有預設實現,使用時直接傳入引數構造出來即可,4種構造方法:
ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects)
ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects)
ArrayAdapter(Context context, int textViewResourceId, List<T> objects)
ArrayAdapter(Context context, int textViewResourceId, T[] objects)
ArrayAdapter不能實現類似setting應用的介面,它只能指定listview前面的圖示都一樣。SimpleAdapter可以實現這種效果。
2) SimpleAdapter
建構函式:SimpleAdapter(Context context, List<? extends Map<String,?>> data, int resource, String[] from, int[] to);
----data:繫結的資料,是一個List集合。
----resource:R.layout.list_item,資料顯示對應的佈局。
----from[]: map集合裡面資料的key。
----to[]:佈局檔案裡面的id。from和to用於資料跟view物件間建立一個對映關係。
android對話方塊
通知對話方塊
//使用AlertDailog包下的Builder
new AlertDialog.Builder(context)
.setTitle("java培訓")
.setCancelable(false) //設定不能通過“後退”按鈕關閉對話方塊
.setMessage("瀏覽傳智播客網站?")
.setCancelable(false) //設定按返回鍵無法關閉對話方塊---取消和確認均可以關閉對話方塊。
.setPositiveButton("確認",
new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialoginterface, int i){
Uri uri = Uri.parse("http://www.itcast.cn/");//開啟連結
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.show();//顯示對話方塊
上面程式碼採用的是一個鏈式呼叫,像setTitle()、setMessage()這些方法,他們的返回值都是當前對話方塊物件。選項列表對話方塊
---裡面有一個ListView控制元件
final String[] items = {"java", ".net", "php"};
new AlertDialog.Builder(SenderNotificationActivity.this).setTitle("選擇語言")
.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(), items[item],
Toast.LENGTH_SHORT).show();
}
}).show();//顯示對話方塊
也可以加按鈕,意義不大。單選對話方塊
final String[] items = {"java", ".net", "php"};
new AlertDialog.Builder(SenderNotificationActivity.this).setTitle("選擇語言")
.setSingleChoiceItems(items, 1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(), items[item],
Toast.LENGTH_SHORT).show();
dialog.cancel();
}
}).show();//顯示對話方塊
setSingleChoiceItems()的第二個引數是設定預設選項,選項索引從0開始,-1代表不選擇任何選項。多選對話方塊
final String[] items = {"java", ".net", "php"};
new AlertDialog.Builder(SenderNotificationActivity.this).setCancelable(false)
.setTitle("選擇語言")
.setMultiChoiceItems(items, new boolean[]{false,true,false}, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if(isChecked){
Toast.makeText(getApplicationContext(), items[which],
Toast.LENGTH_SHORT).show();
}
}
})
.setPositiveButton("確認",
new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialoginterface, int i){
dialoginterface.dismiss();
}
})
.show();//顯示對話方塊
進度條
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal" // 改變為長條的樣式
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100" // 設定進度條的最大刻度
android:progress="0" /> // 設定當前的進度值
進度對話方塊
有2種方式可以開啟進度對話方塊
方式一:
ProgressDialog.show(this, "請稍等", "資料正在載入中...", true);
方式二:
final ProgressDialog pd = new ProgressDialog(this);
pd.setIcon(android.R.drawable.ic_dialog_alert);
pd.setTitle("請稍候");
pd.setMessage("正在下載中...");
// 修改進度條的樣式
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMax(100);
pd.show(); // 彈出進度對話方塊時, 預設把進度設定為0
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
SystemClock.sleep(100);
pd.incrementProgressBy(5);
if(pd.getMax() == pd.getProgress()) {
System.out.println("下載完成了..");
pd.dismiss(); // 把對話方塊給關閉掉
break;
}
}
}
}).start();
注:pd.show(),//彈出進度對話方塊時,預設把進度設定為0,所以pd.setProgress()放在show()之後才生效。ProgressDialog和ProgressBar,可以在子執行緒中重新整理,內部已封裝了handler物件,進行了特殊處理。
android常用控制元件
Spinner控制元件,下拉單選列表框,列表顯示方式也是ListView。
有2種使用方式
方式一:
佈局檔案中新增Spinner控制元件:
<Spinner
android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
在activity中執行程式碼
Spinner mSpinner = (Spinner) findViewById(R.id.spinner);
String[] items = {"java", ".net", "c#", "php", "c", "c++"};
ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
mSpinner.setAdapter(mAdapter);
mSpinner.getSelectedItemPosition();//獲取被選中項的索引,從0開始。
方式二:
在佈局檔案中設定Spinner控制元件的entries屬性,這時是使用android系統預設樣式,控制元件樣式與方式一略有不同:
<Spinner
android:id="@+id/spinner"
android:entries="@array/lagu" // 指定展示的資料
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
// 定義在strings.xml檔案中
<string-array name="lagu">
<item>java</item>
<item>.net</item>
<item>c#</item>
<item>c</item>
<item>c++</item>
<item>java</item>
<item>.net</item>
<item>c#</item>
<item>c</item>
<item>c++</item>
</string-array>
AutoCompleteTextView 自動提示文字框佈局檔案中:
<AutoCompleteTextView
android:id="@+id/actv"
android:completionThreshold="1" // 設定從第一個字元開始提示, 預設值為: 2
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
activity中程式碼:AutoCompleteTextView actv = (AutoCompleteTextView) findViewById(R.id.actv);
String[] items = {"老方", "老黎", "老馮", "張澤華", "張三", "張衝", "王1", "王昭珽", "王友軍", "王友紅"};
ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
actv.setAdapter(mAdapter);
MultiAutoCompleteTextView 多個自動提示文字框程式碼與AutoCompleteTextView基本一樣,只是activity中多了一個步驟:
// 設定一個分隔符號: 逗號
mactv.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
android Style樣式(作用在控制元件上),主題(作用在activity上)
樣式寫在res/styles.xml檔案中,在佈局檔案中用style="@style/textview_style",其中textview_style為styles.xml檔案中樣式的名稱。
樣式可繼承。
<style name="textview_style">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">10dip</item>
<item name="android:layout_marginLeft">20dip</item>
<item name="android:layout_marginRight">20dip</item>
<item name="android:layout_marginTop">10dip</item>
<item name="android:background">#3300FF00</item>
<item name="android:paddingBottom">15dip</item>
<item name="android:paddingLeft">60dip</item>
<item name="android:paddingRight">60dip</item>
<item name="android:paddingTop">15dip</item>
<item name="android:textColor">#0000FF</item>
<item name="android:textSize">25sp</item>
</style>
<style name="textview_style_red" parent="textview_style">
<item name="android:textColor">#FF0000</item>
</style>
主題, 作用在Activity
<style name="custom_theme">
<item name="android:windowBackground">@drawable/a</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
<style name="custom_theme_1" parent="custom_theme">
<item name="android:windowBackground">@drawable/b</item>
</style>
---#00FF00,#後面再加2個16進位制數,表示透明度。
---主題也可以自定義,也是styles.xml新增style標籤。
---自定義主題時,對activity中的屬性,不會有程式碼提示。
前景透明主題自定義