ViewEaxmple
Android 課程的一些作業,不小心寫太多了,就順便把它寫成教學文章,裡面有 AutoComplete TextView (自動建議的 EditText) Draw2D (2D繪圖) FrameAnimation () GridView (網格選單) ListView (列表選單) RecyclerCardView (恢復選單) Spinner (下拉式選單) TweenAnimation ()
Install / Use
/learn @Kantai235/ViewEaxmpleREADME
在 Android 上的各種 Layout 教學
AutoComplete TextView (自動建議的 EditText)
Draw2D (2D繪圖)
FrameAnimation ()
GridView (網格選單)
ListView (列表選單)
RecyclerCardView (恢復選單)
Spinner (下拉式選單)
TweenAnimation ()
/**
* 講義:
* http://epaper.gotop.com.tw/PDFSample/AEL016331.pdf
*
* 採用:
* https://github.com/Bearded-Hen/Android-Bootstrap
*/
主頁(activity_main)

我們在這裡只需要賦予所有的按鈕擁有換頁功能。
// 如果首頁 Button 被點擊了,就觸發這項事件。
public void main_Button_Click(View view) {
// 建立 Intent 元件(應用程式的意圖或使用者的意圖)
Intent intent = new Intent();
// 篩選 view 傳入的 R.id
switch (view.getId()) {
// 如果這個 R.id 是 R.id.main_button_autoCompleteTextView
case R.id.main_button_autoCompleteTextView:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, autoCompleteTextViewActivity.class);
break;
// 如果這個 R.id 是 R.id.main_button_draw2d
case R.id.main_button_draw2d:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, draw2dActivity.class);
break;
// 如果這個 R.id 是 R.id.main_button_framAnimation
case R.id.main_button_framAnimation:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, frameAnimationActivity.class);
break;
// 如果這個 R.id 是 R.id.main_button_gridView
case R.id.main_button_gridView:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, gridViewActivity.class);
break;
// 如果這個 R.id 是 R.id.main_button_listView
case R.id.main_button_listView:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, listViewActivity.class);
break;
// 如果這個 R.id 是 R.id.main_button_recyclerCardView
case R.id.main_button_recyclerCardView:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, recyclerCardViewActivity.class);
break;
// 如果這個 R.id 是 R.id.main_button_spinner
case R.id.main_button_spinner:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, spinnerActivity.class);
break;
// 如果這個 R.id 是 R.id.main_button_tweenAnimation
case R.id.main_button_tweenAnimation:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, tweenAnimationActivity.class);
break;
// 如果這個 R.id 都不是以上的種類
default:
// 賦予 Intent(意圖) 事件的起始地、目的地
intent.setClass(this, MainActivity.class);
break;
}
// 啟動換頁活動
startActivity(intent);
// 結束當前的這一頁活動
finish();
}
AutoComplete TextView (自動建議的 EditText)

首先要有個 AutoCompleteTextView,再來我想要在這裡面輸入內容,按下 OK Button(按鈕)後,把資料儲存到程式當中,方便我下一次取值,所以在頁面的部分我們需要一個 AutoCompleteTextView 以及一個 Button。
<AutoCompleteTextView
android:id="@+id/autoCompleteTextViewActivity_autoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textColor="@android:color/white" />
<com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/bootstrapButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:onClick="autoCompleteTextView_Button_Click"
android:text="@android:string/ok"
app:bootstrapBrand="regular"
app:bootstrapSize="lg"
app:buttonMode="regular"
app:roundedCorners="true"
app:showOutline="false" />
然後在程式當中,先設定需要的全域變數:
// 建立全域 AutoCompleteTextView 元件
private AutoCompleteTextView textView;
// 建立全域 ArrayAdapter<String> 轉接器元件
private ArrayAdapter<String> arrayAdapter;
// 建立全域 ArrayList<String> 存值的元件
private ArrayList<String> countries = new ArrayList<>();
接下來我們該思考,當 onCreate 啟動之後,我們必須要程式執行哪些事情,把該載入的元件都先載入完畢,然後指定實數、指定橋接器、指定點擊事件 ... 等等。
// 設定 ArrayAdapter,採用系統預設的 android.R.layout.simple_dropdown_item_1line 樣式,並賦予資料 this.countries
this.arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, this.countries);
// 指定全域 AutoCompleteTextView 元件
this.textView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextViewActivity_autoCompleteTextView);
// 指定閾值的實數
this.textView.setThreshold(1);
// 指定元件的橋接器(Adapter)
this.textView.setAdapter(this.arrayAdapter);
// 指定元件的 Item 如果被點擊的事件
this.textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// 複寫
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 取得被指定 Item 的內容
String item = parent.getItemAtPosition(position).toString();
// 利用吐司訊息 show 出被點擊的內容
Toast.makeText(autoCompleteTextViewActivity.this, item, Toast.LENGTH_SHORT).show();
}
});
再來如果按鈕被點了,我們需要把輸入框的值寫入程式資料當中,以供輸入框下次自動判斷字典。
// OK Button(按鈕)被點擊的事件
public void autoCompleteTextView_Button_Click(View view) {
// 取得 AutoCompleteTextView 輸入框的內容
String editText = this.textView.getText().toString();
// 將 AutoCompleteTextView 輸入框的內容設定為空 ""
this.textView.setText("");
// 如果輸入的內容為空
if (editText.isEmpty()) {
// 利用吐司訊息告知
Toast.makeText(this, "內容不得為空。", Toast.LENGTH_SHORT).show();
// 利用 checkData() 來確認輸入的內容是否重複
} else if (this.checkData(editText)) {
// 利用吐司訊息告知
Toast.makeText(this, editText + " 這個內容已經存在了。", Toast.LENGTH_SHORT).show();
// 如果輸入的內容不為空,且不重複
} else {
// 在 全域 ArrayList<String> 新增資料
this.countries.add(editText);
}
// 刷新 Adapter 橋接器的資料
updatedData(this.countries);
}
可是只是把資料寫進程式當中,還是沒辦法讓程式找尋歷史字典,因為我們必須去更新橋接器裡面的資料,所以又寫了一個方法。
// 更新 Adapter 橋接器的資料
private void updatedData(ArrayList<String> itemsArrayList) {
// 刪除 Adapter 底層的資料
this.arrayAdapter.clear();
// 如果 itemsArrayList 不是空的
if (itemsArrayList != null) {
// 利用 foreach 探索所有 itemsArrayList 的值
for (String str : itemsArrayList) {
// 新增資料到 arrayAdapter 底層
this.arrayAdapter.insert(str, this.arrayAdapter.getCount());
}
}
// 更新 this.arrayAdapter 的資料
this.arrayAdapter.notifyDataSetChanged();
}
到這邊基本上就沒問題了,但還有些許 Bug 存在,如果什麼都不輸入,或者輸入重複的下去儲存資料,那程式會跑錯誤,所以我們必須要有一個驗證機制,來防止這種事情發生。
// 確認 this.countries 的值是否重複,如果重複則回傳 true,如果沒有則回傳 false。
private boolean checkData(String _str) {
// 利用 foreach 探索所有 this.countries 的值
for (String str : this.countries) {
// 判斷 _str 是否等同 str
if (_str.equals(str)) {
// 回傳 true
return true;
}
}
// 回傳 false
return false;
}
Draw2D (2D繪圖)

請參閱:
https://github.com/JeasonWong/SlackLoadingView
另外一些注意事項:
/**
* 在新建 Draw2D 畫布時,必須注意這個地方:
* <專案名.畫布名稱 ... />
*/
FrameAnimation ()

GridView (網格選單)、ListView (列表選單) 需要用到的 PostAdapter
我們必須設計一個 Adapter(轉接器) 來給予 GridView (網格選單)、ListView (列表選單) 使用,所以新建一個空的 class 並且繼承(extends) BaseAdapter 這個抽象類別(abstract),並且去實作一些必須實作的方法,如果對 Android 原生有興趣的話,可以把文件打開來看,或者是到 Android Developer 去欣賞。
// 自建一個 PostAdapter(轉接器),並繼承 BaseAdapter
public class PostAdapter extends BaseAdapter {
// Code ...
}
首先我們必須實作的方法有四個,分別為 getCount()、getItem()、getItemId()、getView(),程式碼及解說大概如下:
// (1)複寫長度方法
@Override
public int getCount() {
// 回傳 Post(Cell) 的長度
return postList.size();
}
// (2)複寫取得 Post(Cell) 的方法
@Override
public Object getItem(int position) {
// 回傳目標 Post(Cell),例如被點到10號 Post(Cell),就會回傳 postList.get(10))
// 像 onItemClick 事件的 (... int position ...)
return postList.get(position);
}
// (3)複寫取得 Post(Cell) 編號的方法
@Override
public long getItemId(int position) {
// 回傳目標 Post(Cell) 的編號,例如被點到 10 號 Post(Cell),就會回傳 10 號
// 像 onItemClick 事件的 (... long id)
return postList.get(position).getArg();
}
// (4)複寫取得目標 Post(Cell) 畫面(Item View) 的方法
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 如果 convertView 是空的
if (convertView == null)
// 就給它一個 View,這個 View 是自訂的 activity_list_view_cell
convertView = layoutInflater.inflate(this.cellLayout, parent, false);
// 取得目標 Post 的資料
Post post = postList.get(position);
// 抓取 convertView 的 ImageView,並指定它顯示的圖片
((ImageView) convertView.findViewById(R.id.activity_list_view_cell_imageView)).setImageResource(post.getImage());
// 抓取 convertView 的 TextView(Arg),並指定它顯示的內容
((TextView) convertView.findViewById(R.id.activity_list_view_cell_arg)).setText(String.valueOf(post.getArg()));
// 抓取 convertView 的 TextView(Name),並指定它顯示的內容
((TextView) convertView.findViewById(R.id.activity_list_view_cell_name)).setText(post.getName());
// 將整個 convertView 回傳
return convertView;
}
再來我們必須定義種子包(Post):
// 存放資料的種子
class Post {
// 定義 ImageView 的 R.id
protected int imageId;
// 定義 TextView(Arg) 的值
protected int arg;
// 定義 TextView(Name) 的值
protected String name;
public Post(int imageId, int arg, String name) {
this.setImage(imageId);
this.setArg(arg);
this.setName(name);
}
public int getImage() {
return this.imageId;
}
public int getArg() {
return this.arg;
}
public String getName() {
return this.name;
}
private void setImage(int imageId) {
this.imageId = imageId;
}
private void setArg(int arg) {
this.arg = arg;
}
private void setName(String name) {
this.name = name;
}
}
最後我們把該用一用的弄一弄:
protected int cellLayout;
protected LayoutInflater layoutInflater;
protected List<Post> p
