Material Design(一)
一.標題欄ToolBar
一個用來替代ActionBar的控件。
(1)隱藏原本的ActionBar
註冊文件的application中有
android:theme="@style/AppTheme">
theme在res/style中定義
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
有不同的可選值,帶ActionBar就是在這裏定義的.DarkActionBar是深色主題,
沒有ActionBar可以這樣 Theme.AppCompat.Light.NoActionBar和Theme.AppCompat.NoActionBar,有Light是淺色主題,陪襯顏色是深色,沒有就是主體顏色是深色,陪襯顏色是淺色。這裏有很多可選值,根據需求選擇,什麼透明窗口啥的都有。
(2)佈局文件引進控件
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
></androidx.appcompat.widget.Toolbar>
(3)res目錄下新建一個menu文件夾,然後新建menu,定義一個 菜單在頂部,豐富控件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/backup"
android:title="BackUp"
android:icon="@drawable/ic_launcher_foreground"
app:showAsAction="always"
/>
<item
android:id="@+id/delete"
android:title="Delete"
android:icon="@drawable/ic_launcher_foreground"
app:showAsAction="ifRoom"
/>
<item
android:id="@+id/setting"
android:title="Setting"
android:icon="@drawable/ic_launcher_foreground"
app:showAsAction="withText"
/>
</menu>
app:showAsAction指定按鈕的顯示位置。withText表示以文字形式顯示在菜單中,屏幕不顯示;always表示永遠顯示在Toolbar中,屏幕空間不夠則不顯示;ifRoom表示屏幕空間足夠的情況下顯示在Toolbar中,不夠的話顯示在菜單中;never表示永遠顯示在菜單中。
Toolbar中只顯示圖標,菜單中的Action按鈕只顯示文字
(4)把ToolBar設置一下,將菜單顯示進去
然後繼續在MainActivity中加入以下內容
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar=(Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar,menu);
return super.onCreateOptionsMenu(menu);
}
二.滑動菜單DrawerLayout
將一些菜單隱藏起來,不放在主屏幕上,通過滑動顯示出來。
(1)通過DrawerLayout進行簡單實現
DrawerLayout是一個佈局,允許放入兩個直接子控件,一個是主屏幕顯示的內容,另一個是滑動菜單中顯示的內容,定義一個佈局
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/></LinearLayout>
<TextView
android:id="@+id/drawerTextView"
android:text="This is a menu"
android:layout_gravity="start"
android:background="#FFF"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.drawerlayout.widget.DrawerLayout>
這裏主佈局就是上面那個LinearLayout,滑動的部分是一個TextView,也可以是其他控件。這裏layout_gravity屬性很重要,一定要加,不然沒有效果,可選值,left,right分別是從左向右和從右向左滑動,還有start,會根據系統語言判斷,如果是從左向右語言,比如漢語英語就從左向右滑動,否則從右向左滑動。
(2)針對有的人不知道可以滑動,可以設置一個按鈕來點擊實現效果,在Toolbar中有自帶的實現這一個功能的按鈕叫HomeAsUp,它默認是一個返回箭頭,返回上一個活動。
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawerLayout=(DrawerLayout)findViewById(R.id.drawerlayout);
ActionBar actionBar=getSupportActionBar();
if(actionBar!=null){
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_launcher_foreground);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
drawerLayout.openDrawer(GravityCompat.START);
break;
}
return true;
}
首先獲取actionBar,這裏是ToolBar實現的,ActionBar actionBar=getSupportActionBar();
然後具體設置一下
if(actionBar!=null){
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_launcher_foreground);
}
setDisplayHomeAsUpEnabled()讓導航按鈕顯示出來
setHomeAsUpIndicator可以設置裏面的圖標然後重寫onOptionsItemSelected()方法來實現這個按鈕的點擊事件,這個按鈕的id永遠都是android.R.id.home,然後調用drawerLayout.openDrawer(GravityCompat.START);把滑動菜單展示出來,傳入一個Gravity參數,保證這裏和XML中行爲一致,傳入GravityCompat.START。
三.NavigationView
優化滑動菜單界面。
(1)首先引進依賴
在這裏可以引進最新Design Support依賴
https://developer.android.com/topic/libraries/support-library/packages#design
圖片圓形化工具
https://github.com/hdodenhof/CircleimageView
implementation 'com.android.support:design:28.0.0'
implementation 'de.hdodenhof:circleimageview:3.0.0'
(2)準備一個menu,在NavigationView顯示具體菜單項
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_call"
android:title="Call"
android:icon="@drawable/ic_launcher_foreground" />
<item
android:icon="@drawable/ic_launcher_foreground"
android:title="Friends"
android:id="@+id/nav_friends"
/>
<item
android:icon="@drawable/ic_launcher_foreground"
android:title="Task"
android:id="@+id/nav_task"
/>
<item
android:icon="@drawable/ic_launcher_foreground"
android:title="Mail"
android:id="@+id/nav_mail"
/>
<item
android:icon="@drawable/ic_launcher_foreground"
android:title="Location"
android:id="@+id/nav_location" />
</group>
</menu>
裏面的checkableBehavior屬性定義爲single表示每個item只能單選。
再準備headerLayout在滑動頁面中顯示頭部佈局,自己隨便定義一個就好
(3)修改DrawerLayout中的佈局文件代碼
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/></LinearLayout>
<com.google.android.material.navigation.NavigationView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_view"
android:layout_gravity="start"
app:menu="@menu/nav"
app:headerLayout="@layout/headerlayout" />
</androidx.drawerlayout.widget.DrawerLayout>
(4)在MainActivity中添加以下代碼
NavigationView navigationView=(NavigationView)findViewById(R.id.nav_view);
navigationView.setCheckedItem(R.id.nav_call);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
drawerLayout.closeDrawers();
return false;
}
});
navigationView.setCheckedItem(R.id.nav_call);設置默認選中選項call。接下來給它添加一個點擊事件,這裏點擊任何菜單項都關閉滑動菜單。
四.懸浮按鈕(FloatingActionButton)
Design Support一個控件,使用需要依賴,colorAccent作爲按鈕顏色。
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/floatingActionButton"
android:layout_gravity="bottom|end"
android:layout_margin="5dp"
android:src="@drawable/ic_launcher_foreground"
app:elevation="8dp"
/>
elevation表示投影,數字越大,投影區域越大,顏色越淺。
然後在MainActivity中設置該按鈕點擊事件
FloatingActionButton floatingActionButton=(FloatingActionButton)findViewById(R.id.floatingActionButton);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"Clicked",Toast.LENGTH_SHORT).show();
}
});
五.SnackBar
類似於Toast的提示工具,在提示中加入一個交互按鈕,點擊按鈕可以進行一些額外操作
FloatingActionButton floatingActionButton=(FloatingActionButton)findViewById(R.id.floatingActionButton);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Toast.makeText(MainActivity.this,"Clicked",Toast.LENGTH_SHORT).show();
Snackbar.make(view,"Data Delete",Snackbar.LENGTH_SHORT).setAction("Undo", new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"Data Restore",Toast.LENGTH_SHORT).show();
}
}).show();
}
});
}
不同的地方是Snackbar第一個參數是View,只要是當前頁面任意一個View就可以,Snackbar會使用這個View自動查找最外層佈局。
六.CoordinatorLayout
依然是Design Support裏面的,是一個加強版FrameLayout,可以監聽其所有子控件的各種事件,自動做出最爲合理的相應。比如進行偏移,確保控件不會遮擋。
將之前項目的FrameLayout替換成CoordinatorLayout就可以了。
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/floatingActionButton"
android:layout_gravity="bottom|end"
android:layout_margin="5dp"
android:src="@drawable/ic_launcher_foreground"
app:elevation="8dp"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
可以看到現在Snackbar彈出來的窗口與按鈕不遮擋了