UI元件:AdapterView及子類(二)
自動完成文字框(AutoCompleteTextView)
AutoCompleteTextView是從EditView派生出來的。它實際上也是一個文字編輯框,當用戶輸入一定字元之後,自動完成會顯示一個下拉選單,供使用者選擇,當用戶選擇了某個選單項之後,AutoCompleteTextView按使用者選擇自動填寫該文字框。
使用AutoCompleteTextView,只要為其設定一個Adapter,該Adapter封裝了AutoCompleteTextView預設的提示資訊。
AutoCompleteTextView還派生了一個字類MultiAutoCompleteTextView,該子類的功能與AutoCompleteTextView基本相似,只是MultiAutoCompleteTextView允許輸入多個提示項,提示項以分隔符分隔。可用setTokenizer()方法來設定分隔符。
佈局檔案如下所示:
<?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">
<AutoCompleteTextView
android:id="@+id/auto"
android:layout_width ="match_parent"
android:layout_height="wrap_content"
android:completionHint="請選擇您喜歡的圖書:"
android:dropDownHorizontalOffset="10dp"
android:completionThreshold="1"/>
<MultiAutoCompleteTextView
android:id="@+id/mauto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"/>
</LinearLayout>
android:completionThreshold 設定使用者至少輸入幾個字元才會顯示提示
android:dropDownHorizontalOffset 設定下拉選單與文字框之間的水平偏移,下拉選單預設與文字框左對齊
android:completionHint 設定下拉選單的提示標題
Activity中的程式碼如下所示:
public class AutoCompleteTextViewActivity extends AppCompatActivity {
private AutoCompleteTextView auto;
private MultiAutoCompleteTextView mAuto;
private String[] books = new String[]{"瘋狂Android講義","瘋狂Java講義","瘋狂XML講義","瘋狂Ajax講義"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auto_complete_text_view);
auto = (AutoCompleteTextView) findViewById(R.id.auto);
mAuto = (MultiAutoCompleteTextView) findViewById(R.id.mauto);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,books);
auto.setAdapter(adapter);
mAuto.setAdapter(adapter);
//MultiAutoCompleteTextView設定分隔條
mAuto.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
}
}
介面效果如下所示:
網格檢視(GridView)
GridView與ListView有著相同的父類:AbsListView。它們之間的區別在於GridView可以顯示多行多列,而ListView只能顯示一列。
下面演示如何實現帶預覽的圖片瀏覽器,效果圖如下:
佈局檔案程式碼如下:
<?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">
<GridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:horizontalSpacing="2dp"
android:verticalSpacing="2dp"
android:numColumns="4"
android:gravity="center"/>
<ImageView
android:id="@+id/image"
android:layout_width="240dp"
android:layout_height="240dp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
android:horizontalSpacing 設定各元素之間的水平間距
android:verticalSpacing 設定各元素之間的垂直間距
android:numColumns 設定列數
Activity的程式碼如下:
public class GridViewActivity extends AppCompatActivity {
private GridView gridView;
private ImageView imageView;
private int[] imageIds = new int[]{R.drawable.bomb5,R.drawable.bomb6,R.drawable.bomb7,R.drawable.bomb8,
R.drawable.bomb9,R.drawable.bomb10,R.drawable.bomb11,R.drawable.bomb12,
R.drawable.bomb13,R.drawable.bomb14,R.drawable.bomb15,R.drawable.bomb16};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grid_view);
gridView = (GridView) findViewById(R.id.grid_view);
imageView = (ImageView) findViewById(R.id.image_view);
List<Map<String,Object>> listItems = new ArrayList<>();
for (int i = 0; i < imageIds.length; i++) {
Map<String,Object> item = new ArrayMap<>();
item.put("image",imageIds[i]);
listItems.add(item);
}
SimpleAdapter adapter = new SimpleAdapter(this,listItems,R.layout.ceil,new String[]{"image"},new int[]{R.id.image1});
gridView.setAdapter(adapter);
//新增列表項單擊的監聽器
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//顯示被單擊的圖片
imageView.setImageResource(imageIds[position]);
}
});
}
}
R.layout.ceil檔案對應的程式碼如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/image1"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
可展開的列表元件(ExpandableListView)
ExpandableListView是ListView的子類。
它把應用中的列表項分為幾組,每組又可包含多個列表項。
它所顯示的列表項應該由ExpandableListAdapter提供,ExpandableListAdapter是一個介面。
與Adapter類似,實現ExpandableListAdapter有三種常用方法。
擴充套件BaseExpandableListAdapter(ExpandableListAdapter的子類)實現ExpandableListAdapter
使用SimpleExpandableListAdapter(BaseExpandableListAdapter的子類) 將兩個List集合包裝成ExpandableListAdapter
使用SimpleCursorTreeAdapter(BaseExpandableListAdapter的實現類)將Cursor中的資料包裝成SimpleCursorTreeAdapter
下面程式通過自定義的ExpandableListAdapter為ExpandableListView提供列表項。
當擴充套件BaseExpandableListAdapter時,關鍵是實現如下4個方法:
getGroupCount() : 該方法返回的是包含的組列表項的數量。
getGroupView() : 該方法返回的View物件將作為組列表項。
getChildrenCount() : 該方法返回的是特定組所包含的子列表項的數量。
getChildView() : 該方法返回的View物件將作為特定組、特定位置的子列表項。
佈局檔案程式碼如下:
<ExpandableListView
android:id="@+id/expandable_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
建立一個類,繼承BaseExpandableListAdapter,程式碼如下:
package com.example.administrator.adapterviewinfo;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MyAdapter extends BaseExpandableListAdapter{
private int[] logos = new int[]{R.drawable.p,R.drawable.z,R.drawable.t};
private String[] armTypes = new String[]
{ "神族兵種", "蟲族兵種", "人族兵種"};
private String[][] arms = new String[][]
{
{ "狂戰士", "龍騎士", "黑暗聖堂", "電兵" },
{ "小狗", "刺蛇", "飛龍", "自爆飛機" },
{ "機槍兵", "護士MM" , "幽靈" }
};
private Context context;
public MyAdapter(Context context) {
this.context = context;
}
@Override
public int getGroupCount() {
return armTypes.length;
}
@Override
public int getChildrenCount(int groupPosition) {
return arms[groupPosition].length;
}
/**
* 獲取指定組位置處的組資料
* @param groupPosition
* @return
*/
@Override
public Object getGroup(int groupPosition) {
return armTypes[groupPosition];
}
/**
* 獲取指定組位置,指定子列表項處的子列表項資料
* @param groupPosition
* @param childPosition
* @return
*/
@Override
public Object getChild(int groupPosition, int childPosition) {
return arms[groupPosition][childPosition];
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
/**
* 該方法決定每個組選項的外觀
* @param groupPosition
* @param isExpanded
* @param convertView
* @param parent
* @return
*/
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
ImageView logo = new ImageView(context);
logo.setImageResource(logos[groupPosition]);
linearLayout.addView(logo);
TextView textView = getTextView();
textView.setText(getGroup(groupPosition).toString());
linearLayout.addView(textView);
return linearLayout;
}
/**
* 該方法決定每個子選項的外觀
* @param groupPosition
* @param childPosition
* @param isLastChild
* @param convertView
* @param parent
* @return
*/
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
TextView textView = getTextView();
textView.setText(getChild(groupPosition,childPosition).toString());
return textView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
private TextView getTextView(){
AbsListView.LayoutParams params = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,64);
TextView textView = new TextView(context);
textView.setLayoutParams(params);
textView.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT);
textView.setPadding(36,0,0,0);
textView.setTextSize(17);
return textView;
}
}
Activity中的程式碼如下所示:
public class ExpandableListViewActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_expandable_list_view);
ExpandableListView expandableListView = (ExpandableListView) findViewById(R.id.expandable_list_view);
MyAdapter myAdapter = new MyAdapter(this);
expandableListView.setAdapter(myAdapter);
}
}
效果圖如下所示 :
Spinner
Spinner就是一個列表選擇框。
Spinner和Gallery(如今已過時)都繼承了AbsSpinner。
若下拉列表框中的列表項是確定的,只要為Spinner指定android:entries屬性即可實現Spinner。
若需要動態決定下拉列表項的內容,可以使用Adapter為Spinner新增列表項。
下面定義了兩個Spinner,一個指定了android:entries屬性,另一個使用Adapter為Spinner新增列表項。
佈局檔案如下所示:
<?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" >
<!--指定顯示Spinner元件的陣列-->
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/list"/>
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
@array/list對應的檔案內容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="list">
<item>AbsListView</item>
<item>AbsSpinner</item>
<item>AdapterViewAnimator</item>
</string-array>
</resources>
Activity中的檔案如下所示:
public class SpinnerActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner);
String[] arr = new String[]{"孫悟空","豬八戒","唐僧"};
Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,arr);
spinner.setAdapter(adapter);
}
}
效果如下所示:
AdapterViewFlipper
AdapterViewFlipper繼承自AdapterViewAnimator。
AdapterViewFlipper每次只顯示一個元件,可以通過showPrevious()和showNext()方法控制該元件顯示上一個、下一個元件。
AdapterViewFlipper支援的Xml屬性如下:
XML屬性 | 相關方法 | 說明 |
---|---|---|
android:autoStart | startFlipping() | 設定顯示該元件是否自動播放 |
android:flipInterval | setFlipInterval(int) | 設定自動播放的時間間隔 |
下面的例項使用AdapterViewFlipper實現圖片的自動播放。
佈局檔案程式碼如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<AdapterViewFlipper
android:id="@+id/adapter_view_flipper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:flipInterval="5000" />
<Button
android:id="@+id/prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="上一個"/>
<Button
android:id="@+id/auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="自動播放"/>
<Button
android:id="@+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="上一個"/>
</RelativeLayout>
Activity中的程式碼如下所示:
public class AdapterViewFlipperActivity extends AppCompatActivity implements View.OnClickListener{
private int[] imageIds = new int[]
{ R.drawable.shuangzi, R.drawable.shuangyu,
R.drawable.chunv, R.drawable.tiancheng, R.drawable.tianxie,
R.drawable.sheshou, R.drawable.juxie, R.drawable.shuiping,
R.drawable.shizi, R.drawable.baiyang, R.drawable.jinniu,
R.drawable.mojie };
private AdapterViewFlipper adapterViewFlipper;
private Button prev;
private Button next;
private Button auto;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_adapter_view_flipper);
initUI();
BaseAdapter adapter = new BaseAdapter() {
@Override
public int getCount() {
return imageIds.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(AdapterViewFlipperActivity.this);
imageView.setImageResource(imageIds[position]);
//設定圖片的縮放方式
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
//設定圖片的佈局引數
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return imageView;
}
};
adapterViewFlipper.setAdapter(adapter);
}
private void initUI() {
adapterViewFlipper = (AdapterViewFlipper) findViewById(R.id.adapter_view_flipper);
prev = (Button) findViewById(R.id.prev);
auto = (Button) findViewById(R.id.auto);
next = (Button) findViewById(R.id.next);
prev.setOnClickListener(this);
auto.setOnClickListener(this);
next.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.prev:
prev();
break;
case R.id.auto:
auto();
break;
case R.id.next:
next();
break;
default:
break;
}
}
/**
* 顯示下一個元件
*/
private void next() {
//顯示下一個元件
adapterViewFlipper.showNext();
//停止自動播放
adapterViewFlipper.stopFlipping();
}
/**
* 自動播放
*/
private void auto() {
//開始自動播放
adapterViewFlipper.startFlipping();
}
/**
* 顯示上一個元件
*/
private void prev() {
//顯示上一個元件
adapterViewFlipper.showPrevious();
//停止自動播放
adapterViewFlipper.stopFlipping();
}
}
效果圖如下所示:
StackView
StackView也是AdapterViewAnimator的子類。
StackView將以堆疊的方式顯示多個列表項。
StackView提供了兩種控制其View元件的方式:
拖走StackView處於頂端的View,下一個View將會顯示出來。將上一個View拖進StackView,將使其顯示出來。
通過呼叫StackView的showPrevious()、showNext()控制顯示上一個、下一個元件。
佈局檔案如下所示:
<?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">
<!--android:loopViews設定迴圈到最後一個元件時是否自動“轉頭”到第一個元件-->
<StackView
android:id="@+id/stack_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:loopViews="true"/>
<Button
android:id="@+id/prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="上一個"/>
<Button
android:id="@+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="下一個"/>
</LinearLayout>
Activity中的程式碼如下所示:
public class StackViewActivity extends AppCompatActivity{
private int[] imageIds = new int[]{
R.drawable.bomb5,R.drawable.bomb6,R.drawable.bomb7,R.drawable.bomb8,
R.drawable.bomb9,R.drawable.bomb10,R.drawable.bomb11,R.drawable.bomb12,
R.drawable.bomb13,R.drawable.bomb14,R.drawable.bomb15,R.drawable.bomb16
};
private StackView stackView;
private Button prev;
private Button next;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stack_view);
initUI();
List<Map<String,Object>> listItems = new ArrayList<>();
for (int i = 0; i < imageIds.length; i++) {
Map<String,Object> item = new ArrayMap<>();
item.put("image",imageIds[i]);
listItems.add(item);
}
SimpleAdapter adapter = new SimpleAdapter(this,listItems,R.layout.ceil,new String[]{"image"},new int[]{R.id.image1});
stackView.setAdapter(adapter);
}
private void initUI() {
stackView = (StackView) findViewById(R.id.stack_view);
prev = (Button) findViewById(R.id.prev);
next = (Button) findViewById(R.id.next);
prev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//顯示上一個元件
stackView.showPrevious();
}
});
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//顯示下一個元件
stackView.showNext();
}
});
}
}
R.layout.ceil檔案對應的程式碼如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/image1"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
效果如下所示:
拖動頂端的圖片或者點選“下一個”都可以切換到下一張圖片。