1.常用控件:
Button:
android:textAllCaps="false"
—— 用于設(shè)定文本是否大寫
EditText:
android:hint="Something"
—— 指定一段提示性文本
android:inputType="password"
—— 設(shè)定輸入類型
android:maxLines="2"
—— 設(shè)定最大行數(shù)
ImageView:
android:src="@drawable/img_1"
—— 指定一張圖片
setImageResource(R.drawable.img_2)
—— 設(shè)定圖片資源
ProgressBar:
android:visibility="visible"/"invisible"/"gone"
—— 設(shè)定可見屬性
setVisibility(View.VISIBLE/View.INVISIBLE/View.GONE)
—— 設(shè)定可見屬性
getVisibility()
—— 獲取當(dāng)前可見屬性
style="?android:attr/progressBarStyleHorizontal"
android:max="100"
—— 設(shè)定水平進(jìn)度條,并限制最大值為 100
getProgress() setProgress()
—— 獲取當(dāng)前進(jìn)度和設(shè)置進(jìn)度
AlertDialog:
new AlertDialog.Builder(Context context)
—— 創(chuàng)建警告對話框
setTitle()
—— 設(shè)定標(biāo)題
setMessage
—— 設(shè)定內(nèi)容
setCancelable
—— 設(shè)定是否能返回取消對話框
setPositiveButton()
—— 設(shè)置確定按鈕
setNegativeButton()
—— 設(shè)置取消按鈕
show()
—— 將對話框顯示出來
ProgressDialog:
new ProgressDialog(Context context)
—— 創(chuàng)建進(jìn)度對話框
setTitle()
—— 設(shè)定標(biāo)題
setMessage
—— 設(shè)定內(nèi)容
setCancelable
—— 設(shè)定是否能返回取消對話框
show()
—— 將對話框顯示出來
dismiss()
—— 關(guān)閉對話框
setIndeterminate()
—— 設(shè)定不確定狀態(tài)
2.詳解基本布局:
RelativeLayout:
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
—— 根據(jù)父布局來擺放控件
android:layout_above="@id/button"
android:layout_below="@id/button"
android:layout_toLeftOf="@id/button"
android:layout_toRightOf="@id/button"
—— 根據(jù)控件來擺放
android:layout_alignLeft="@id/button"
android:layout_alignTop="@id/button"
—— 對齊控件邊緣,當(dāng)一個控件去引用另一個控件的 id 時,該控件一定要定義在引用控件的后面,不然會出現(xiàn)找不到 id 的情況
PercentLayout:
implementation 'com.android.support:percent:24.2.1'
—— 在 app/build.gradle 的 dependencies 閉包中添加依賴聲明
android.support.percent.PercentFrameLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
—— 在布局文件中添加完整包名和 app命名空間
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"
—— 設(shè)定空間百分比大小
3.自定義 View:
所有控件都是直接或間接繼承自 View,所用的所有布局都是直接或間接繼承自 ViewGroup。View 是 Android 中最基本的一種 UI組件,而 ViewGroup 是一種特殊的 View,它可以包含很多 子View 和 子ViewGroup,是一個用于放置控件和布局的容器
引入布局:
重新定義一個 title.xml 標(biāo)題欄布局,在 activity_main.xml 中引入
<include layout="@layout/title"/>將系統(tǒng)自帶的標(biāo)題欄隱藏
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
actionBar.hide();
}
- 創(chuàng)建自定義控件:
——新建一個 java 文件,讓其作為標(biāo)題欄控件,并編寫具體邏輯操作
Public class TitleLayout extends LinearLayout implements View.OnClickListener{
public TitleLayout(Context context, AttributeSet attrs){
super(context, attrs);
/**
* inflate() 第二個參數(shù)是給加載好的布局再添加一個父布局
* 這里指定為 TitleLayout
*/
LayoutInflater.from(context).inflate(R.layout.title, this);
Button titleBack = findViewById(R.id.title_back);
Button titleEdit = findViewById(R.id.title_edit);
titleBack.setOnClickListener(this);
titleEdit.setOnClickListener(this);
}
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.title_back:
// 編寫邏輯
break;
case R.id.title_edit:
// 編寫邏輯
break;
}
}
}
——在 activity_main.xml 中添加此自定義控件
<com.example.uitest.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
4.探究 ListView:
簡單用法:
- 直接在 activity_main.xml 中加入控件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
- 修改 MainActivity.java
public class MainActivity extends AppCompatActivity {
/**
* 簡單使用 String 類型數(shù)組來測試
*/
private String[] data = {"Apple", "Pear", "Grape", "Banana", "Orange", "Cherry",
"Apple", "Pear", "Grape", "Banana", "Orange", "Cherry", "Watermelon",
"Apple", "Pear", "Grape", "Banana", "Orange", "Cherry", "Watermelon",
"Apple", "Pear", "Grape", "Banana", "Orange", "Cherry", "Watermelon",};
/**
* 數(shù)組中的數(shù)據(jù)無法直接傳遞給 ListView ,因此需要借助適配器來完成,
* 新建一個數(shù)組適配器,泛型指定為 String ,這里使用了系統(tǒng)內(nèi)置的布局
* android.R.layout.simple_list_item_1 作為 ListView 子項(xiàng)布局的 id ,
* 最后調(diào)用 ListView 的 setAdapter() 方法將構(gòu)建好的適配器對象傳入,
* 這樣 ListView 和數(shù)據(jù)之間的關(guān)聯(lián)就建立完成了。
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this,android.R.layout.simple_list_item_1, data);
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
}
步驟:
- 添加 ListView 控件
- 添加需要適配的數(shù)據(jù)
- 生成適配器對象,泛型指定為數(shù)據(jù)類型
- 生成 ListView 的實(shí)例
- 調(diào)用 ListView 的
setAdapter()方法,將構(gòu)建好的適配器對象傳入
定制 ListView 的界面:
- 定義一個類作為 ListView適配器 的適配類型:
public class Fruit {
private String name;
private int imageId;
public Fruit(String name, int imageId){
this.name = name;
this.imageId = imageId;
}
public String getName(){
return name;
}
public int getImageId(){
return imageId;
}
}
- 定義一個 ListView子項(xiàng)布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/fruit_image"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp"/>
</LinearLayout>
- 創(chuàng)建一個自定義適配器:
public class FruitAdapter extends ArrayAdapter<Fruit>{
// ListView 子項(xiàng)布局id
private int resourceId;
public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects){
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
Fruit fruit = getItem(position);
View view;
ViewHolder viewHolder;
if(convertView == null){
view = LayoutInflater.from(getContext())
.inflate(resourceId, parent, false);
viewHolder = new ViewHolder();
viewHolder.fruitImage = view.findViewById(R.id.fruit_image);
viewHolder.fruitName = view.findViewById(R.id.fruit_name);
view.setTag(viewHolder);
}else{
view = convertView;
viewHolder = (ViewHolder)view.getTag();
}
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setText(fruit.getName());
return view;
}
class ViewHolder{
ImageView fruitImage;
TextView fruitName;
}
}
—— 對 convertView 進(jìn)行重用,并且使用 ViewHolder 對控件的實(shí)例進(jìn)行緩存,以便提升 ListView 的運(yùn)行效率
- 修改 MainActivity 的代碼:
public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruit(); // 初始化水果數(shù)據(jù)
FruitAdapter adapter = new FruitAdapter(this,R.layout.fruit_item, fruitList);
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
private void initFruit(){
for(int i = 0; i < 2; i++){
Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
fruitList.add(apple);
Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
fruitList.add(banana);
// 省略以下重復(fù)代碼
}
}
}
ListView 的點(diǎn)擊事件:
- 參數(shù):
- parent 用于識別是哪個 ListView
- view 是當(dāng)前 ListView 的 item 的布局,可以使用這個 view,獲取里面的控件 id 后操作控件
- position 是當(dāng)前 item 在 fruitList 中的位置
- id 是當(dāng)前 item 在 ListView 里的第幾行的位置
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(adapter);
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();
}
});
步驟:
- 創(chuàng)建適配器的適配類,定義子項(xiàng)布局
- 創(chuàng)建自定義適配器,并提升運(yùn)行效率
- 修改 MainActivity 代碼,添加點(diǎn)擊事件
5. 探究 RecyclerView:
- 相較于 ListView,RecyclerView 的擴(kuò)展性更好,可以輕松實(shí)現(xiàn)縱向布局和橫向布局等,同時還可以輕松實(shí)現(xiàn)子項(xiàng)中任意控件或布局的點(diǎn)擊事件,優(yōu)化了 ListView 的不足之處,代碼的語義也更加清晰
基本用法:
- 在
app/build.gradle的dependencies中添加依賴庫
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
- 在
activity_main.xml中添加控件,由于RecyclerView并不是內(nèi)置在系統(tǒng) SDK 中,所以需要寫完整包路徑
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
- 定義一個和 ListView 中同樣的實(shí)體類和子項(xiàng)布局,此處略過
- 自定義一個適配器,繼承自
RecyclerView.Adapter,并將泛型指定為FruitAdapter.ViewHolder,ViewHolder 是定義在 FruitAdapter 中的內(nèi)部類
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{
private List<Fruit> mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder{
ImageView fruitImage;
TextView fruitName;
/**
* @param view View 參數(shù)通常是 RecyclerView 子項(xiàng)的最外層布局,
* 因此可以通過 findViewById() 來獲取布局內(nèi)的控件實(shí)例。
*/
ViewHolder(View view){
super(view);
fruitImage = view.findViewById(R.id.fruit_image);
fruitName = view.findViewById(R.id.fruit_name);
}
}
FruitAdapter(List<Fruit> fruitList){
mFruitList = fruitList;
}
/**
* 此方法用于創(chuàng)建 ViewHolder 實(shí)例,在方法中將 fruit_item 布局加載出來,
* 然后創(chuàng)建一個 ViewHolder 實(shí)例,并把加載出來的布局傳入到構(gòu)造函數(shù)中,
* 最后將 ViewHolder 實(shí)例返回。
*
* @param parent 將新視圖綁定到適配器位置后添加到其中的父布局,
* 在這里指 RecyclerView 的布局。
* @param viewType 新視圖的視圖類型,可以通過此參數(shù)擴(kuò)展
* 不同類型的子項(xiàng)視圖。
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
// 為子項(xiàng)加載傳入的 R.layout.fruit_item 這個子項(xiàng)布局
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fruit_item, parent, false);
return new ViewHolder(view);
}
/**
* 此方法用于對子項(xiàng)的數(shù)據(jù)進(jìn)行賦值,會在每個子項(xiàng)被滾動到屏幕內(nèi)
* 的時候執(zhí)行,這里通過 position 參數(shù)得到當(dāng)前項(xiàng)的 Fruit 實(shí)例,
* 然后再將數(shù)據(jù)設(shè)置到 ViewHolder 的 ImageView 和 TextView 當(dāng)中。
*
* @param holder 由 onCreateViewHolder() 方法中傳來的返回值
* @param position 子項(xiàng)在適配器中的位置
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position){
Fruit fruit = mFruitList.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
}
/**
* 此方法用于告訴 RecyclerView 一共有多少子項(xiàng)
*/
@Override
public int getItemCount(){
return mFruitList.size();
}
}
- 修改 MainActivity 中的代碼,在獲取布局管理器之后可以調(diào)用布局管理器的方法
setOrientation()來改變方向排列,傳入LinearLayoutManager.HORIZONTAL即可修改為水平方向排列
public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();// 初始化水果數(shù)據(jù)
RecyclerView recyclerView = findViewById(R.id.recycler_view);
/**
* 使用 LayoutManager 來指定 RecyclerView 的布局方式,這里使用線性布局,
* 可以實(shí)現(xiàn)和 ListView 一樣的效果。
*/
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits(){
for(int i = 0; i < 100; i++){
Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
fruitList.add(apple);
Fruit orange = new Fruit("Orange", R.drawable.orange_pic);
fruitList.add(orange);
Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
fruitList.add(banana);
Fruit lemon = new Fruit("Lemon", R.drawable.lemon_pic);
fruitList.add(lemon);
Fruit strawberry = new Fruit("Strawberry", R.drawable.sstrawberry_pic);
fruitList.add(strawberry);
}
}
}
- 網(wǎng)格布局 & 瀑布流布局
GridLayoutManager manager = new GridLayoutManager();
(Context context, int spanCount);
—— 網(wǎng)格布局
StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager();
(int spanCount, int orientation);
—— 瀑布流布局
點(diǎn)擊事件
- 修改
FruitAdapter.java即可
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{
private List<Fruit> mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder{
View fruitView;
ImageView fruitImage;
TextView fruitName;
/**
* @param view View 參數(shù)通常是 RecyclerView 子項(xiàng)的最外層布局,
* 因此可以通過 findViewById() 來獲取布局內(nèi)的控件實(shí)例。
*/
ViewHolder(View view){
super(view);
fruitView = view;
fruitImage = view.findViewById(R.id.fruit_image);
fruitName = view.findViewById(R.id.fruit_name);
}
}
/**
* 此方法用于創(chuàng)建 ViewHolder 實(shí)例,在方法中將 fruit_item 布局加載出來,
* 然后創(chuàng)建一個 ViewHolder 實(shí)例,并把加載出來的布局傳入到構(gòu)造函數(shù)中,
* 最后將 ViewHolder 實(shí)例返回。
*
* @param parent 將新視圖綁定到適配器位置后添加到其中的父布局,
* 在這里指 RecyclerView 的布局。
* @param viewType 新視圖的視圖類型,可以通過此參數(shù)擴(kuò)展
* 不同類型的子項(xiàng)視圖。
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
// 為子項(xiàng)加載傳入的 R.layout.fruit_item 這個子項(xiàng)布局
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;
}
}