Android學習筆記(2)

myxs發表於2017-03-24

UI

常用控制元件

1:TextView

android:gravity="center",指定文字的對齊方式為位於控制元件內部的中部,即水平居中和垂直居中

2:Button

android:textAllCaps="false"禁止自動大寫字母轉換

為Button的點選事件註冊一個監聽器
註冊匿名類方式

button.setOnClickListener(new View.OnClickListener(){
    @Onverride
    public void onClick(View v){
        //新增處理邏輯
    }
}

通過實現介面的方式
類實現View.OnCLickListener介面
給按鈕註冊監聽器:

button.setOnCLickListener(this)
    @Onverride
    public void onClick(View v){
        switch(v.getId(){
            case R.id.button:
                //新增處理邏輯
                break;
            default:
        }
    }

3: EditText

android:hint屬性指定提示性的文字
android:maxLines="2"指定最大行數為2行,文字超過時會自動滾動
獲取到EditText中的內容:

private EditText editText;
editText = (EditText) findViewByid
String text = editText.geetText().toString();

4:ImageView

android:src="@drawable/img_1"

動態更改圖片:

imageView.setImageResource(R.drawable.img_2);

5:ProgressBar

android:visibilitty="visible/invisible/gone"控制控制元件的可見性
程式碼中

progress.setVisible(View.VISIBLE)
style="?android:attr/progressBarStyleHorizontal"

android:max="100"圓形進度條

動態更改進度條的進度
int progress = progressBar.getProgress();
progress +=10;
progressBar.setProgress(progress);

6:AlertDialog

AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Dialog Title");
dialog.setMessage("something important");
dialog.setCancelable(false);
dialog.setPositviButton("OK",new DialogInterface.OnClickListener(){
    @Onverride
    {
        public void onClick(){DialogInterface dialog, int which){
        }
    };
dialog.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){
        @Onverride
        public void onClick(DialogInterface dialog, int which){
        }
    }
}
dialog.show();

7:ProgressDialog

ProgressDialog progressDialog = new ProgressDialog(MainActivity.his);
progressDialog.setTitle("ProgressDialog");
porgressDialog.setMessage("Loaing...");
progressDialog.setCancelable(true);
progressDialog.show();

當setCancelable中傳入false,表示不能通過Back鍵來取消的,當資料載入完成後必須要呼叫ProgressDialog.dismiss來關閉對話方塊

8 四種佈局

線性佈局:android:orientation屬性指定了排列方向,可選vertical,預設為horizontal
android:layout_gravity屬性用於指定控制元件在佈局中的對其位置。注意在指定了某種排列方式後,如水平排列,那麼只有垂直方向的對齊方式才會有效。

可以使用androdi:layout_weight按比例排列

<EidtText
android:layout_weight="1"
android:layout_width="0" />
<Button
android:layout_width="wrap"/>

指定部分控制元件的layout_weight

相對佈局

RelativeLayout通過相對定位的方式控制控制元件在佈局中的位置

android:layout_alingParentLeft|Rihgt|Top|Bottom="true"
android:layout_centerInParent="true"

每個控制元件都是相對父佈局進行定位,也可以相對於控制元件定位

android:layout_above="@id/button3"
android:layout_toLeftOf="@id/button3"

幀佈局

所有控制元件預設都位於佈局的左上角,後新增的控制元件會遮擋之前定義的控制元件
使用layout_gravity屬性指定控制元件在佈局中的對齊方式,類似LinearLayout

百分比佈局

buidl.gradle中新增布局庫的依賴

compile 'com.android.support:percent:25.0.0"


定義一個app的名稱空間
包括PercentFrameLayout和PercentRelativeLayout
通過layout_layoutheightPercent控制height和width的百分比
通過layout_gravity控制對齊方式

自定義控制元件

1.引入佈局
    實現一個自定義標題欄。標題欄佈局,然後把標題欄佈局引入。如
    title.xml

        <LinearLayout
        ...>
        <Button
        .../>
        <EditText
        .../>
        <Button
        .../>
        </LinearLayout>
    activity_main.xml中引入標題欄佈局

        <include layout=“@layout/title" />

        ActionBar actionBar = getSupportActionBar();
        if (actionBar!=null)
            actionBar.hide();

缺點:佈局中的控制元件如果需要響應事件,必須在每個活動中都要編寫事件註冊的程式碼。

2.建立自定義控制元件

public class TitleLayout extends LinearLayout{
    public TitleLayout(Context context, AttributeSet attrs){
        super(context, attrs);
        LayoutInflater.form(context).inflate(R.layout.title,this);
    }
}

通過LayoutInflater的from方法構建LayoutInflater物件,呼叫infalte方法動態載入一個佈局檔案

在佈局檔案中新增自定義控制元件

<com.example.uitest.TitleLayout
android:layot_width...
.../>

為標題欄中按鈕註冊點選事件

public class TitleLayout...{
    ...
    Button back  = (Button) findViewById(R.id.back);
    Button edit = (Button) findViewById(R.id.edit);
    back.setOnClickListener(new OnClickListener(){
        @Onverride
        public void onClick(View v){
            ((Activity)getContext()).finish();
        }
    });
    edit.setOnClickListener(new OnClickListener(){
        @Onverride
        public void onClick(View v){
            //新增處理邏輯
        }
    });
}

9:ListView

佈局中新增ListView控制元件

<LinearLayout
...>
    <ListView
        android:id..
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

不能直接將大量資料傳給ListView顯示,需要藉助介面卡。 比如ArrayAdapter,通過泛型來指定適配的資料型別, 然後在建構函式中將要適配的資料傳入。

ArrayAdatpter的建構函式中依次傳入當前上下文、ListView子項佈局的id、以及要適配的資料。 此處使用 android.R.layout.simple_list_item_1作為ListView子項佈局的id,作為Android內建的佈局檔案,只有一個TextView,簡單顯示一段文字

private String[] data={...};//資料
...
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, data);//若需要改變子項佈局,新建ListView子項佈局檔案
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);//將介面卡物件傳遞,使ListView和資料之間建立關聯

定製ListView介面

ListView子項抽象為一個物件,即需要新建一個實體類,作為ListView介面卡的適配型別,如同前面的Strinig型別物件。

public class Fruit{
        private String name;
        private int imageId;
        ...
    }

為ListView子項新建一個佈局檔案fruit_item.xml,包括水果圖片和水果名稱

<LinearLayout
... >
    <ImageView
        android:id="@+id/fruit_image"
        .. />
    <TextView
        android:id="@+id/fruit_name"
        ... />
</LinearLayout>

新建一個繼承ArrayAdapter的自定義介面卡FruitAdapter,泛型指定為前面建立的實體類Fruit

public class FruitAdapter extends ArrayAdapter<Fruit>{
    private int resourceId;
    public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects){
        super...;//上下文,子項佈局id和資料傳遞進來
        resourceId = textViewResourceId;
        }
    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        Fruit fruit = getItem(position);//獲取當前項的Fruit例項
        View view = LayoutInflater.from(getContext()).infalte(resourceId, parent, false);
        ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
        TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fruitName.setText(fruit.getName());
        return view;
}

為每個進入到螢幕內的子項獲取Fruit例項,載入子項佈局,並通過Fruit例項的資料設定子項佈局內控制元件即圖片和文字的值。 在活動中建立FruitAdapter介面卡的例項,併為ListView設定介面卡

private List<Fruit> fruitList = new ArrayList<>();
...

FruitAdapter adpater = new FruitAdpater(MainActivity.this, R.layout.fruit_item, fruitList);
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
...

優化ListView快取子項佈局和快取控制元件的例項

View view;
if (convertView == null){
    view = LayoutInflater.from(getContext()).infalte(resourceId, parent, false);
}else{
    view = currentView;
    }

新建一個內部類ViewHolder,對控制元件例項快取

 @Override
public View getView(int position, View convertView, ViewGroup parent) {
    Fruit fruit = getItem(position); // 獲取當前項的Fruit例項
    View view;
    ViewHolder viewHolder;
    if (convertView == null) {
        view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
        viewHolder = new ViewHolder();
        viewHolder.fruitImage = (ImageView) view.findViewById (R.id.fruit_image);
        viewHolder.fruitName = (TextView) view.findViewById (R.id.fruit_name);
        view.setTag(viewHolder); // 將ViewHolder儲存在View中
    } else {
        view = convertView;
        viewHolder = (ViewHolder) view.getTag(); // 重新獲取ViewHolder
    }
    viewHolder.fruitImage.setImageResource(fruit.getImageId());
    viewHolder.fruitName.setText(fruit.getName());
    return view;
}

class ViewHolder {

    ImageView fruitImage;

    TextView fruitName;

}

ListView點選事件

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {
            Fruit fruit = fruitList.get(position);
            Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
        }
    });

為ListView註冊一個監聽器,點選某個子項時,回撥onItemClick方法,判斷點選的是哪個子項

缺點:不能實現橫向滾動,只能縱向滾動

10:RecyclerView 需要在app/build.gradle新增依賴庫

compile 'com.android.support:recyclerview-v25.0.0'

在佈局檔案中新增RecyclerView控制元件

<LinearLayout
... />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width..
        />
</LinearLayout>

與ListView一樣,需要實體類Fruit和子項佈局檔案fruit_item.xml。稍微不同的是介面卡FruitAdapter,繼承RecyclerView.Adapter,泛型指定為FruitAdapter.ViewHolder,ViewHolder是FruitAdapter內部類

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{

    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder {
        View fruitView;
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view) {
            super(view);
            fruitView = view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);
        }
    }

    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        final ViewHolder holder = new ViewHolder(view);
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked view " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        holder.fruitImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked image " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }

 @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

    @Override
    public int getItemCount() {
        return mFruitList.size();
    }
}

資料列表,ViewHolder,View和ListView相同用法 ListView的getView方法可以理解為拆分為OnCreateViewHolder和onBindViewHolder,獲取子項佈局,以及ViewHolder物件,利用ViewHolder物件對控制元件的值進行控制,最後還重寫了getItemCount方法。 在活動中的程式碼和ListView差不多

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    StaggeredGridLayoutManager layoutManager = new
            StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(layoutManager);
    FruitAdapter adapter = new FruitAdapter(fruitList);
    recyclerView.setAdapter(adapter);

多了XXXXXLayoutManager用於指定RecyclerView的佈局方式,比如LinearLayoutManager表示線性佈局,效果類似ListView。還可以實現橫向滾動,設定layoutManager的佈局排列方向屬性

layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

GridLayoutManager和StaggeredGridLayoutManager分別可以實現網格佈局和瀑布流佈局

StaggeredGridLayoutManager layoutManager = new
            StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(layoutManager);//列數和佈局排列方式2個引數

RecyclerView的點選事件

不同於ListView的setOnItemClickListener註冊監聽器方法,RecyclerView必須要自己給子項具體的View註冊點選事件 如前面FruitAdapter中的程式碼,ViewHolder不僅有子項佈局中的控制元件快取還儲存了子項最外層佈局例項,在onCreateViewHolder中註冊點選事件,分別為最外層佈局和ImageView註冊了點選事件。為子項佈局中的任意控制元件或佈局註冊點選事件。

相關文章