轉載請標明出處:http://blog.csdn.net/donkor_/article/details/78819081
前言:
最近做了一個純Kotlin開發的Android開源軟件,“DeepNight-in-kotlin,陪你度過每一個深夜”,剛好用到了Material Design設計風格。功能完善好,代碼簡單貼一下,方便日後查看和使用。
本文demo包含以下要點:
DrawerLayout+NavigationView+ToolBar的使用
Fragment簡單封裝,實現懶加載
下面看下效果圖。
由上面的效果圖可以看出,其中的佈局包括3部分,主體佈局,抽屜菜單未滑出時的顯示佈局 ,抽屜菜單的頭部佈局 ,抽屜菜單的菜單項佈局
基本配置
在Project的 build.gradle 中的dependencies添加:
implementation 'com.android.support:design:26.1.0'
主佈局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawer_layout">
<!--主內容-->
<include layout="@layout/toolbar_layout"/>
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity = "start"
app:headerLayout="@layout/head_layout"
app:itemBackground="?attr/colorPrimary"
app:menu="@menu/menu">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
注:可以看出除了DrawerLayout包裹了NavigationView控件,其中menu指的的是抽屜菜單菜項,headerLayout指的是抽屜菜單的頭部佈局
抽屜菜單header佈局drawer_header.xml
<?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:gravity="center"
android:orientation="vertical"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/head_view"
android:layout_marginTop="30dp"/>
<TextView
android:id="@+id/tv_user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Donkor" />
</LinearLayout>
抽屜菜單menu佈局文件menu.xml
<?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">
<group android:id="@+id/ground1">
<item
android:id="@+id/nav_item1"
android:icon="@mipmap/icon_all"
android:title="item1"
app:showAsAction="ifRoom" />
</group>
<group android:id="@+id/ground2">
<item
android:id="@+id/nav_item2"
android:icon="@mipmap/icon_bosom"
android:title="item2"
app:showAsAction="ifRoom" />
<item
android:id="@+id/nav_item3"
android:icon="@mipmap/icon_buttocks"
android:title="item3"
app:showAsAction="ifRoom" />
<item
android:id="@+id/nav_item_stockings"
android:icon="@mipmap/icon_stockings"
android:title="item4"
app:showAsAction="ifRoom" />
</group>
</menu>
注:加了group的話,在drawerlayout裏會以group爲單位劃線。
回過頭,我們再來看看DrawerLayout下導入的toolbar_layout佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/blue"
app:contentInsetStart="0dp">
<TextView
android:id="@+id/tv_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:text="Title"
android:textColor="@android:color/white" />
</android.support.v7.widget.Toolbar>
<LinearLayout
android:id="@+id/fl_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</LinearLayout>
注:可以看到Toolbar控件包裹到TextView,該View用來做ToolBar標題。效果圖中由於我們使用到了ToolBar的左側圖標,使用ToolBar自帶的標題會導致標題不居中,所以不建議使用。底下的LinearLayout用作主體佈局內容
注:綜上Material Design的佈局基本貼完。之後看下Theme自定義style。修改ToolBar左側圖標顏色
<resources>
<!-- Base application theme. -->
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">@style/AnimationActivity</item>
</style>
<!--Activity動畫-->
<style name="AnimationActivity" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/slide_in_left</item>
<item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
<item name="android:activityCloseEnterAnimation">@anim/slide_in_right</item>
<item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
</style>
<style name="AppTheme" parent="AppBaseTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@android:color/white</item>
<item name="colorPrimaryDark">@android:color/white</item>
<!-- 溢出菜單圖標顏色-->
<item name="colorControlNormal">@android:color/white</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@android:color/white</item>
</style>
</resources>
主佈局Kotlin類MainActivity
package com.donkor.demo.materialdesign
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.view.GravityCompat
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.toolbar_layout.*
class MainActivity : AppCompatActivity() {
private var firstFragment: FirstFragment? = null
private var secondFragment: SecondFragment? = null
private var threeFragment: ThreeFragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/*設置ActionBar
*不使用toolbar自帶的標題
*/
toolbar.title = ""
setSupportActionBar(toolbar)
/*顯示Home圖標*/
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
/*設置ToolBar標題,使用TestView顯示*/
tv_bar_title.text = "Item1"
/*設置Drawerlayout的開關,並且和Home圖標聯動*/
val mToggle = ActionBarDrawerToggle(this, drawer_layout, toolbar, 0, 0)
drawer_layout.addDrawerListener(mToggle)
/*同步drawerlayout的狀態*/
mToggle.syncState()
/*設置監聽器*/
setListener()
initFragment(savedInstanceState)
}
private fun initFragment(savedInstanceState: Bundle?) {
if (savedInstanceState != null) {
//異常情況
val mFragments: List<Fragment> = supportFragmentManager.fragments
for (item in mFragments) {
if (item is FirstFragment) {
firstFragment = item
}
if (item is SecondFragment) {
secondFragment = item
}
if (item is ThreeFragment) {
threeFragment = item
}
}
} else {
firstFragment = FirstFragment()
secondFragment = SecondFragment()
threeFragment = ThreeFragment()
val fragmentTrans = supportFragmentManager.beginTransaction()
fragmentTrans.add(R.id.fl_content, firstFragment)
fragmentTrans.add(R.id.fl_content, secondFragment)
fragmentTrans.add(R.id.fl_content, threeFragment)
fragmentTrans.commit()
}
supportFragmentManager.beginTransaction().show(firstFragment)
.hide(secondFragment)
.hide(threeFragment)
.commit()
}
/*設置監聽器*/
private fun setListener() {
nav_view.setNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.nav_item1 -> {
tv_bar_title.text = "Item1"
supportFragmentManager.beginTransaction().show(firstFragment)
.hide(secondFragment)
.hide(threeFragment)
.commit()
}
R.id.nav_item2 -> {
tv_bar_title.text = "Item2"
supportFragmentManager.beginTransaction().show(secondFragment)
.hide(firstFragment)
.hide(threeFragment)
.commit()
}
R.id.nav_item3 -> {
tv_bar_title.text = "Item3"
supportFragmentManager.beginTransaction().show(threeFragment)
.hide(firstFragment)
.hide(secondFragment)
.commit()
}
}
drawer_layout.closeDrawer(GravityCompat.START)
true
}
}
}
注:MainActivity中的註釋寫的很詳細 ,這裏不再做過多的解釋
BaseFragment基類,實現懶加載
package com.donkor.demo.materialdesign
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
/**
* Created by donkor on 2017/12/16.
*/
abstract class BaseFragment : Fragment() {
var rootView: View? = null
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
if (rootView == null) {
rootView = inflater?.inflate(getLayoutResources(), container, false)
}
return rootView
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
/**
* 判斷該Fragment是否顯示在用戶面前
*/
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (!hidden)
loadData()
}
abstract fun getLayoutResources(): Int
abstract fun initView()
/**
* 懶加載,當前Fragment顯示的時候才進行網絡請求
* 如果數據不需要每次都刷新,可以先判斷數據是否存在
* 數據不存在 -> 進行網絡請求 數據存在 -> 什麼都不做
*/
abstract fun loadData()
}
FirstFragment
class FirstFragment : BaseFragment() {
override fun loadData() {
//懶加載,當前Fragment顯示的時候才進行網絡請求
//如果數據不需要每次都刷新,可以先判斷數據是否存在
//數據不存在 -> 進行網絡請求 數據存在 -> 什麼都不做
}
override fun getLayoutResources(): Int {
return R.layout.fragment_frist
}
override fun initView() {
}
}
Fragment的佈局fragment_frist.xml
<?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"
android:layout_gravity="center"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FirstFragment"
android:textSize="25sp"/>
</LinearLayout>
注:SecondFragment、ThreeFragment的代碼跟佈局和FirstFragment類似,這裏就不貼了。meun用到的icon如有需要則可以下載demo去拿。
DeepNight-in-kotlin項目使用地址:https://github.com/ChenYXin/DeepNight-in-kotlin
Demo_CSDN 下載地址 :http://download.csdn.net/download/donkor_/10161518
About me
Email :[email protected]
Android開發交流QQ羣 : 537891203