一個Demo學會用Android相容包新控制元件
阿新 • • 發佈:2019-01-28
前言
偉大的Google為Android推出了一系列的相容包,最新的就是Design Support Library了,這裡我們結合v7和v4中的幾個控制元件,來主要學習Design Support Library中的幾個新控制元件!一個Demo學會用它們!
效果動圖GIF:
Design Support Library Demo
學習內容
通過本例項可以學習到以下內容:
- Drawerlayout和NavigationView實現優雅的Google範兒側邊欄;
- 新控制元件CoordinatorLayout、AppBarLayout、Toolbar、FloatingActionButton的用法,以及Toolbar的漸變隱藏動畫效果;
- 官方Tabs元件TabLayout和ViewPager結合實現主介面內容區域;
- SwipeRefreshLayout和RecyclerView結合實現下拉重新整理,以及RecyclerView的資料介面卡RecyclerView.Adapter<ViewHolder>的用法,還有RecyclerView中item的點選事件的實現方法;
- 卡片式CardView的用法;
- 類似Toast的新控制元件Snackbar的用法。
佈局檔案
在原始碼中學習Android,是有種身臨其境的感覺的。
學習Android解釋再多程式碼都沒有用,因為解釋過了還是不會用。因此,我們這裡將佈局檔案XML原始碼貼出來供學習,放心,所有知識點都已經註釋在原始碼中。
styles.xml原始碼
<resources>
<style name="AppTheme" parent="MyThemeBlue"></style>
<!-- 藍色為主色調 -->
<style name="MyThemeBlue" parent="Theme.AppCompat.Light.NoActionBar">
<!--選中狀態icon的顏色和字型顏色-->
<item name="colorPrimary">@color/main_blue_light</item >
<item name="colorPrimaryDark">@color/main_blue_dark</item>
<item name="colorAccent">@color/main_blue_light</item>
<!--正常狀態下字型顏色和icon顏色-->
<item name="android:textColorPrimary">@color/main_white</item>
</style>
</resources>
colorPrimary、colorPrimaryDark、colorAccent、textColorPrimary的含義,請看博文《Android L+ Theme 與 Toolbar 例項》。
主佈局activity_my.xml原始碼(重點)
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/id_drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 第一個位置 -->
<!-- 你的主介面內容,必須放置在Drawerlayout中的第一個位置
根據自己的需要來放置控制元件,
例如:LinearLayout佈局或者RelativeLayout佈局;
也可以是單個控制元件,
如 TextView等 -->
<include layout="@layout/content_main" />
<!-- 第二個位置 -->
<!-- 用來放Drawerlayout中的內容,
這裡使用NavigationView來實現類似Google pLay中的側滑欄效果,
必須在build.gradle中新增compile 'com.android.support:design:22.2.0';
另外,如果不需要NavigationView效果,
也可以放置一個普通佈局檔案就是一個普通的側滑欄了。
-->
<!--
注意:
如果使用NavigationView(其他控制元件也是一樣)的特有屬性,需要加上名稱空間:
xmlns:app="http://schemas.android.com/apk/res-auto";
另外,一定要新增android:layout_gravity="left"屬性。
-->
<!--
屬性解析:
app:headerLayout: NavigationView中頭部的head部分的佈局,是自己實現的;
app:menu: 指定Nav中的Menu佈局,就是自己寫Menu中的按鈕,要放在res/menu/資料夾下;
app:itemTextColor: 用來設定Nav中,menu item的顏色選擇器。
還有一些屬性: 和itemTextColor用法一樣,指定一個顏色選擇器,實現不同的顏色效果。
app:itemIconTint:
app:itemBackground:
-->
<android.support.design.widget.NavigationView
android:id="@+id/id_navigationview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:itemTextColor="@color/selector_nav_menu_textcolor"
android:layout_gravity="left" />
</android.support.v4.widget.DrawerLayout>
content_main.xml原始碼(重點)
<?xml version="1.0" encoding="utf-8"?><!--
CoordinatorLayout是這次新新增的一個增強型的FrameLayout,通過它可以實現很多東西:
例如:
1.介面向上滾動逐漸隱藏Toolbar;
2.在其中可以放置浮動的View,就像Floating Action Button。
-->
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/id_coordinatorlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!--
AppBarLayout跟它的名字一樣,把容器類的元件全部作為AppBar。
將AppBarLayout放在CoordinatorLayout中,就可以實現滾動效果。
本例中,TabLayout在介面滾動時,隨著Toolbar的逐漸隱藏,將佔據Toolbar的位置,
達到節省螢幕空間,介面動畫效果的目的。
-->
<android.support.design.widget.AppBarLayout
android:id="@+id/id_appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--
屬性解析:
app:theme:指定Toolbar的樣式,包括ActionbarToggle和popupMenu的指示圖示顏色
app:popupTheme:指定popupMenu溢位後的樣式
app:title: 指定Toolbar中主Title的內容
-->
<!--
app:layout_scrollFlags的意思是:
設定的layout_scrollFlags有如下幾種選項:
scroll: 所有想滾動出螢幕的view都需要設定這個flag- 沒有設定這個flag的view將被固定在螢幕頂部。
enterAlways: 這個flag讓任意向下的滾動都會導致該view變為可見,啟用快速“返回模式”。
enterAlwaysCollapsed: 當你的檢視已經設定minHeight屬性又使用此標誌時,你的檢視只能以最小高度進入,只有當滾動檢視到達頂部時才擴大到完整高度。
exitUntilCollapsed: 當檢視會在滾動時,它一直滾動到設定的minHeight時完全隱藏。
需要注意的是,後面兩種模式基本只有在CollapsingToolbarLayout才有用,
而前面兩種模式基本是需要一起使用的,也就是說,這些flag的使用場景,基本已經固定了。
-->
<android.support.v7.widget.Toolbar
android:id="@+id/id_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:title="@string/toolbar_title" />
<!--
Tabs選項卡,和ViewPager搭配使用可以增大介面的內容展示量,實現各種個性化分類內容展示而不互相干擾!
Google在Design support library中提供官方的Tab元件,它就是TabLayout。
相比Github上面開源的第三方庫,這個更加簡單易用。
有以下常用屬性:
app:tabGravity="fill" 表示TabLayout中的Tabs要佔滿螢幕的width;
app:tabSelectedTextColor:Tab被選中字型的顏色;
app:tabTextColor:Tab未被選中字型的顏色;
app:tabIndicatorColor:Tab指示器下標的顏色;
-->
<android.support.design.widget.TabLayout
android:id="@+id/id_tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabIndicatorColor="@color/main_white" />
</android.support.design.widget.AppBarLayout>
<!--
我們常用的ViewPager,不多說了。你會發現多了一個 app:layout_behavior 屬性,沒錯,
如果你使用CoordinatorLayout來實現Toolbar滾動漸變消失動畫效果,那就必須在它下面的那個控制元件中加入這個屬性,
並且下面的這個控制元件必須是可滾動的。
當設定了layout_behavior的控制元件滑動時,就會觸發設定了layout_scrollFlags的控制元件發生狀態的改變。
-->
<android.support.v4.view.ViewPager
android:id="@+id/id_viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<!--
這是一個浮動按鈕。由於FloatingActionButton是重寫ImageView的,
所有FloatingActionButton擁有ImageView的一切屬性。
屬性介紹:
app:backgroundTint : FAB的背景色。
app:elevation :FAB的陰影效果。
app:rippleColor :設定漣漪的顏色,預設是由背景色生成的暗色調,可以自己指定。
app:pressedTranslationZ :FAB動畫效果,在它被按下的時候陰影就會增大。
-->
<android.support.design.widget.FloatingActionButton
android:id="@+id/id_floatingactionbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:src="@mipmap/ic_action_plusone"
app:backgroundTint="@color/main_blue_light"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
app:rippleColor="@color/main_blue_dark" />
</android.support.design.widget.CoordinatorLayout>
frag_main.xml原始碼(Fragment的佈局)
<?xml version="1.0" encoding="utf-8"?>
<!--
SwipeRefreshLayout是偉大的Google在v4包中給出的下拉重新整理元件。
-->
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/id_swiperefreshlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!--
使用RecyclerView需要在build.gradle中新增
compile 'com.android.support:recyclerview-v7:22.2.0'
-->
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v4.widget.SwipeRefreshLayout>
item_main.xml原始碼(RecyclerView中item)
<!--
CardView就是一個卡片樣式的FrameLayout。
引數介紹:
app:cardBackgroundColor : 背景顏色
app:cardCornerRadius : 設定圓角。
app:cardElevation : 陰影。
app:cardMaxElevation : 最大陰影。
app:cardPreventCornerOverlap : 在v20和之前的版本中新增內邊距,
這個屬性是為了防止卡片內容和邊角的重疊。
app:cardUseCompatPadding : 設定內邊距,v21+的版本和之前的版本仍舊具有一樣的計算方式
-->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/id_cardview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardBackgroundColor="@color/main_blue_light"
app:cardCornerRadius="4dp"
app:cardElevation="5dp"
app:cardMaxElevation="10dp"
app:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<TextView
android:id="@+id/id_textview"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:gravity="center"
android:textColor="@color/main_white"
android:textSize="30sp" />
</android.support.v7.widget.CardView>
menu_nav.xml的原始碼(NavagationView中選單)
<?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_menu_home"
android:icon="@mipmap/ic_home_white_48dp"
android:title="主頁" />
<item
android:id="@+id/nav_menu_categories"
android:icon="@mipmap/ic_sort_by_alpha_white_48dp"
android:title="分類" />
<item
android:id="@+id/nav_menu_feedback"
android:icon="@mipmap/ic_message_white_48dp"
android:title="反饋" />
<item
android:id="@+id/nav_menu_setting"
android:icon="@mipmap/ic_settings_white_48dp"
android:title="設定" />
</group>
</menu>
header_nav.xml原始碼(NavagationView的head)
<?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="220dp"
android:background="@drawable/ic_user_background"
android:gravity="center"
android:orientation="vertical">
<!--
一個顯示圓形頭像的自定義ImageView
-->
<com.sunjiajia.androidnewwidgetsdemo.view.RoundedImageView
android:id="@+id/id_header_face"
android:layout_width="110dp"
android:layout_height="110dp"
android:scaleType="fitXY"
android:src="@drawable/author" />
<TextView
android:id="@+id/id_header_authorname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/header_author_name"
android:textColor="@android:color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/id_header_url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/header_author_url"
android:textColor="@android:color/black"
android:textSize="18sp" />
</LinearLayout>
Java程式碼
Java程式碼寫法比較簡單,這裡只給出RecyclerView.Adapter<ViewHolder>的寫法(包括item點選事件)。
RecyclerView.Adapter<ViewHolder>寫法原始碼
package com.sunjiajia.androidnewwidgetsdemo.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.sunjiajia.androidnewwidgetsdemo.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Monkey on 2015/6/29.
*/
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewHolder> {
// 點選事件介面
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
public OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(OnItemClickListener listener) {
this.mOnItemClickListener = listener;
}
public Context mContext;
public List<String> mDatas;
public LayoutInflater mLayoutInflater;
public MyRecyclerViewAdapter(Context mContext) {
this.mContext = mContext;
mLayoutInflater = LayoutInflater.from(mContext);
// 這裡是模擬資料。
mDatas = new ArrayList<>();
for (int i = 'A'; i <= 'z'; i++) {
mDatas.add((char) i + "");
}
}
/**
* 建立ViewHolder
*/
@Override
public MyRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = mLayoutInflater.inflate(R.layout.item_main, parent, false);
MyRecyclerViewHolder mViewHolder = new MyRecyclerViewHolder(mView);
return mViewHolder;
}
/**
* 繫結ViewHoler,給item中的控制元件設定資料
*/
@Override
public void onBindViewHolder(final MyRecyclerViewHolder holder, final int position) {
//點選事件在這裡實現,主要是利用RecyclerView中填充的佈局控制元件可以被點選這個原理
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(holder.itemView, position);
}
});
// 長點選事件
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mOnItemClickListener.onItemLongClick(holder.itemView, position);
return true;
}
});
}
holder.mTextView.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
}
MyRecyclerViewHolder.java原始碼
package com.sunjiajia.androidnewwidgetsdemo.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import com.sunjiajia.androidnewwidgetsdemo.R;
/**
* Created by Monkey on 2015/6/29.
*/
public class MyRecyclerViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public MyRecyclerViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.id_textview);
}
}
結語
在原始碼中學習Android,是有種身臨其境的感覺的。
整個Demo的原始碼我放在了GitHub上,謝謝star一下~
在看原始碼過程中如果發現什麼問題,請在留言,看到一定回覆。