Android?底部導(dǎo)航停留在屏幕底部,提供應(yīng)用中頂級(jí)視圖之間的導(dǎo)航笔呀。這是在具有向后兼容性的設(shè)計(jì)支持庫中引入的幢踏。當(dāng)應(yīng)用程序有三到五個(gè)頂級(jí)導(dǎo)航時(shí),應(yīng)使用底部導(dǎo)航许师。
本文介紹了底部導(dǎo)航的基礎(chǔ)知識(shí)房蝉,并將其與Fragments相結(jié)合。我們還將學(xué)習(xí)如何通過HTTP調(diào)用獲取JSON?來加載帶有網(wǎng)格數(shù)據(jù)的第一個(gè)片段(使用RecyclerView)微渠。
1.底部導(dǎo)航
可以使用BottomNavigationView組件輕松添加底部導(dǎo)航搭幻。您必須使用引力或相對(duì)屬性才能使其顯示在屏幕底部。
http://schemas.android.com/apk/res/android"
????xmlns:app="http://schemas.android.com/apk/res-auto"
????xmlns:tools="http://schemas.android.com/tools">
????????android:id="@+id/frame_container"
????????android:layout_width="match_parent"
????????android:layout_height="match_parent"
????????app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
????????android:id="@+id/navigation"
????????android:layout_width="match_parent"
????????android:layout_height="wrap_content"
????????android:layout_gravity="bottom"
????????android:background="?android:attr/windowBackground"
????????app:itemBackground="@color/bgBottomNavigation"
????????android:foreground="?attr/selectableItemBackground"
????????app:itemIconTint="@android:color/white"
????????app:itemTextColor="@android:color/white"
????????app:menu="@menu/navigation"/>
這里必須記下幾個(gè)重要的屬性逞盆。
app:menu?- 用于顯示導(dǎo)航項(xiàng)以及圖標(biāo)和文本的菜單資源文件粗卜。
app:itemBackground?- 將背景顏色應(yīng)用于底部導(dǎo)航。
app:itemTextColor?- 底部導(dǎo)航項(xiàng)的文本顏色纳击。
app:itemIconTint?- 底部導(dǎo)航項(xiàng)的圖標(biāo)顏色续扔。
何時(shí)使用底部導(dǎo)航?
根據(jù)設(shè)計(jì)規(guī)范焕数,應(yīng)根據(jù)標(biāo)準(zhǔn)使用以下導(dǎo)航纱昧。
>?導(dǎo)航抽屜?- 當(dāng)頂級(jí)導(dǎo)航具有六個(gè)以上的目的地時(shí)使用。
>?標(biāo)簽?- 當(dāng)有兩個(gè)導(dǎo)航目的地時(shí)使用堡赔。
>?底部導(dǎo)航?- 當(dāng)有三到五個(gè)頂級(jí)目的地時(shí)使用识脆。
在進(jìn)一步研究之前,請(qǐng)快速了解底部導(dǎo)航的設(shè)計(jì)規(guī)范。
現(xiàn)在讓我們通過在Android Studio中創(chuàng)建一個(gè)新項(xiàng)目來嘗試它灼捂。
2.創(chuàng)建新項(xiàng)目
1离例。從File?NewProject在Android Studio中創(chuàng)建一個(gè)新項(xiàng)目,然后從模板中選擇Basic Activity悉稠。
2宫蛆。下載此res文件夾并將drawable添加到項(xiàng)目的res。此文件夾包含底部導(dǎo)航項(xiàng)所需的必要繪圖的猛。
3耀盗。請(qǐng)確保您有設(shè)計(jì)支持庫在你的build.gradle。
的build.gradle
dependencies {
????implementation 'com.android.support:design:26.1.0'
}
4卦尊。將以下顏色叛拷,字符串值添加到colors.xml和strings.xml中。
colors.xml
????#7b4bff
????#6539ba
????#FF4081
????#fe485a
strings.xml中
????Bottom Navigation
????Shop
????Gifts
????Cart
????Profile
5岂却。當(dāng)使用菜單文件呈現(xiàn)底部導(dǎo)航項(xiàng)時(shí)忿薇,在res?菜單文件夾下創(chuàng)建一個(gè)名為navigation.xml的新xml?。
navigation.xml
http://schemas.android.com/apk/res/android">
????????android:id="@+id/navigation_shop"
????????android:icon="@drawable/ic_store_white_24dp"
????????android:title="@string/title_shop"/>
????????android:id="@+id/navigation_gifts"
????????android:icon="@drawable/ic_card_giftcard_white_24dp"
????????android:title="@string/title_gifts"/>
????????android:id="@+id/navigation_cart"
????????android:icon="@drawable/ic_shopping_cart_white_24dp"
????????android:title="@string/title_cart"/>
????????android:id="@+id/navigation_profile"
????????android:icon="@drawable/ic_person_white_24dp"
????????android:title="@string/title_profile"/>
6躏哩。打開主要活動(dòng)的布局文件署浩,即activity_main.xml,并添加BottomNavigationView小部件震庭。這里我們還添加了一個(gè)FrameLayout來在選擇導(dǎo)航項(xiàng)時(shí)加載Fragments瑰抵。
activity_main.xml中
http://schemas.android.com/apk/res/android"
????xmlns:app="http://schemas.android.com/apk/res-auto"
????xmlns:tools="http://schemas.android.com/tools"
????android:id="@+id/container"
????android:layout_width="match_parent"
????android:layout_height="match_parent"
????tools:context="info.androidhive.bottomnavigation.MainActivity">
????????android:id="@+id/frame_container"
????????android:layout_width="match_parent"
????????android:layout_height="match_parent"
????????app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
????????android:id="@+id/navigation"
????????android:layout_width="match_parent"
????????android:layout_height="wrap_content"
????????android:layout_gravity="bottom"
????????android:background="?android:attr/windowBackground"
????????app:itemBackground="@color/bgBottomNavigation"
????????android:foreground="?attr/selectableItemBackground"
????????app:itemIconTint="@android:color/white"
????????app:itemTextColor="@android:color/white"
????????app:menu="@menu/navigation"/>
7∧愦疲現(xiàn)在打開MainActivity.java并按如下所示進(jìn)行修改器联。
>此處,選擇底部導(dǎo)航項(xiàng)時(shí)將調(diào)用OnNavigationItemSelectedListener⌒稣福現(xiàn)在我們只是在選擇導(dǎo)航項(xiàng)時(shí)更改工具欄標(biāo)題拨拓。
MainActivity.java
packageinfo.androidhive.bottomnavigation;
importandroid.os.Bundle;
importandroid.support.annotation.NonNull;
importandroid.support.design.widget.BottomNavigationView;
importandroid.support.design.widget.CoordinatorLayout;
importandroid.support.v4.app.Fragment;
importandroid.support.v4.app.FragmentTransaction;
importandroid.support.v7.app.ActionBar;
importandroid.support.v7.app.AppCompatActivity;
importandroid.view.MenuItem;
importinfo.androidhive.bottomnavigation.fragment.CartFragment;
importinfo.androidhive.bottomnavigation.fragment.GiftsFragment;
importinfo.androidhive.bottomnavigation.fragment.ProfileFragment;
importinfo.androidhive.bottomnavigation.fragment.StoreFragment;
importinfo.androidhive.bottomnavigation.helper.BottomNavigationBehavior;
publicclassMainActivity extendsAppCompatActivity {
????privateActionBar toolbar;
????@Override
????protectedvoidonCreate(Bundle savedInstanceState) {
????????super.onCreate(savedInstanceState);
????????setContentView(R.layout.activity_main);
????????toolbar = getSupportActionBar();
????????BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
????????navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
????????toolbar.setTitle("Shop");
????}
????privateBottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
????????????= newBottomNavigationView.OnNavigationItemSelectedListener() {
????????@Override
????????publicbooleanonNavigationItemSelected(@NonNullMenuItem item) {
????????????Fragment fragment;
????????????switch(item.getItemId()) {
????????????????caseR.id.navigation_shop:
????????????????????toolbar.setTitle("Shop");
????????????????????returntrue;
????????????????caseR.id.navigation_gifts:
????????????????????toolbar.setTitle("My Gifts");
????????????????????returntrue;
????????????????caseR.id.navigation_cart:
????????????????????toolbar.setTitle("Cart");
????????????????????returntrue;
????????????????caseR.id.navigation_profile:
????????????????????toolbar.setTitle("Profile");
????????????????????returntrue;
????????????}
????????????returnfalse;
????????}
????};
}
如果您運(yùn)行該應(yīng)用程序,則可以看到顯示的底部導(dǎo)航氓栈,如下所示渣磷。
3.添加片段
當(dāng)我們準(zhǔn)備好底部導(dǎo)航時(shí),讓我們看看如何在選擇導(dǎo)航菜單項(xiàng)時(shí)切換視圖授瘦。這可以通過使用片段輕松完成醋界。
注意:根據(jù)設(shè)計(jì)規(guī)范使用底部導(dǎo)航時(shí)不應(yīng)使用ViewPager(避免使用橫向運(yùn)動(dòng)在視圖之間轉(zhuǎn)換)
我創(chuàng)建一個(gè)名為四個(gè)片段StoreFragment,GiftsFragment提完,CartFragment和ProfileFragment形纺。
8。通過轉(zhuǎn)到文件?新?片段?片段(空白)創(chuàng)建新片段并將其命名為StoreFragment.java徒欣。同樣也要?jiǎng)?chuàng)建其他三個(gè)片段逐样。
9。打開MainActivity.java并修改底部導(dǎo)航偵聽器,如下所示脂新,以在FrameLayout中加載片段挪捕。
>?loadFragment()?- 將Fragment加載到FrameLayout中。通過傳遞適當(dāng)?shù)钠螌?shí)例争便,在OnNavigationItemSelectedListener回調(diào)中調(diào)用相同的方法级零。
>特定模塊所需的邏輯進(jìn)入適當(dāng)?shù)钠危3諱ainActivity清潔始花。
MainActivity.java
packageinfo.androidhive.bottomnavigation;
importandroid.os.Bundle;
importandroid.support.annotation.NonNull;
importandroid.support.design.widget.BottomNavigationView;
importandroid.support.design.widget.CoordinatorLayout;
importandroid.support.v4.app.Fragment;
importandroid.support.v4.app.FragmentTransaction;
importandroid.support.v7.app.ActionBar;
importandroid.support.v7.app.AppCompatActivity;
importandroid.view.MenuItem;
importinfo.androidhive.bottomnavigation.fragment.CartFragment;
importinfo.androidhive.bottomnavigation.fragment.GiftsFragment;
importinfo.androidhive.bottomnavigation.fragment.ProfileFragment;
importinfo.androidhive.bottomnavigation.fragment.StoreFragment;
importinfo.androidhive.bottomnavigation.helper.BottomNavigationBehavior;
publicclassMainActivity extendsAppCompatActivity {
????privateActionBar toolbar;
????@Override
????protectedvoidonCreate(Bundle savedInstanceState) {
????????super.onCreate(savedInstanceState);
????????setContentView(R.layout.activity_main);
????????toolbar = getSupportActionBar();
????????// load the store fragment by default
????????toolbar.setTitle("Shop");
????????loadFragment(newStoreFragment());
????}
????privateBottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
????????????= newBottomNavigationView.OnNavigationItemSelectedListener() {
????????@Override
????????publicbooleanonNavigationItemSelected(@NonNullMenuItem item) {
????????????Fragment fragment;
????????????switch(item.getItemId()) {
????????????????caseR.id.navigation_shop:
????????????????????toolbar.setTitle("Shop");
????????????????????fragment = newStoreFragment();
????????????????????loadFragment(fragment);
????????????????????returntrue;
????????????????caseR.id.navigation_gifts:
????????????????????toolbar.setTitle("My Gifts");
????????????????????fragment = newGiftsFragment();
????????????????????loadFragment(fragment);
????????????????????returntrue;
????????????????caseR.id.navigation_cart:
????????????????????toolbar.setTitle("Cart");
????????????????????fragment = newCartFragment();
????????????????????loadFragment(fragment);
????????????????????returntrue;
????????????????caseR.id.navigation_profile:
????????????????????toolbar.setTitle("Profile");
????????????????????fragment = newProfileFragment();
????????????????????loadFragment(fragment);
????????????????????returntrue;
????????????}
????????????returnfalse;
????????}
????};
????privatevoidloadFragment(Fragment fragment) {
????????// load fragment
????????FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
????????transaction.replace(R.id.frame_container, fragment);
????????transaction.addToBackStack(null);
????????transaction.commit();
????}
}
現(xiàn)在妄讯,如果您運(yùn)行項(xiàng)目,則可以在選擇導(dǎo)航時(shí)看到加載的片段酷宵。
4.實(shí)現(xiàn)ShopFragment - 在網(wǎng)格中顯示項(xiàng)目
現(xiàn)在我們將看到如何實(shí)現(xiàn)第一個(gè)片段亥贸,即ShopFragment,它以網(wǎng)格方式顯示商店項(xiàng)目浇垦。為了演示炕置,我創(chuàng)建了一個(gè)樣本json,其中包含很少的待售電影男韧。要實(shí)現(xiàn)這一點(diǎn)朴摊,我們所要做的就是獲取json并以網(wǎng)格格式在RecyclerView中顯示數(shù)據(jù)。為了使任務(wù)更簡(jiǎn)單此虑,請(qǐng)按照我的另一篇解釋相同的文章甚纲。
https://api.androidhive.info/json/movies_2017.json
10。打開build.gradle并添加RecyclerView朦前,CardView介杆,Volley和Glide依賴項(xiàng)。
的build.gradle
dependencies {
????// RecyclerView
????compile 'com.android.support:recyclerview-v7:26.1.0'
????// CardView
????compile 'com.android.support:cardview-v7:26.1.0'
????// volley http library
????implementation 'com.android.volley:volley:1.0.0'
????implementation 'com.google.code.gson:gson:2.6.2'
????// glide image library
????implementation 'com.github.bumptech.glide:glide:4.3.1'
}
11韭寸。創(chuàng)建一個(gè)名為MyApplication.java的類春哨,從Application實(shí)現(xiàn)該類。這是一個(gè)單例類恩伺,其中將啟動(dòng)齊射庫赴背。
MyApplication.java
packageinfo.androidhive.bottomnavigation.app;
importandroid.app.Application;
importandroid.text.TextUtils;
importcom.android.volley.Request;
importcom.android.volley.RequestQueue;
importcom.android.volley.toolbox.Volley;
publicclassMyApplication extendsApplication {
????publicstaticfinalString TAG = MyApplication.class
????????????.getSimpleName();
????privateRequestQueue mRequestQueue;
????privatestaticMyApplication mInstance;
????@Override
????publicvoidonCreate() {
????????super.onCreate();
????????mInstance = this;
????}
????publicstaticsynchronizedMyApplication getInstance() {
????????returnmInstance;
????}
????publicRequestQueue getRequestQueue() {
????????if(mRequestQueue == null) {
????????????mRequestQueue = Volley.newRequestQueue(getApplicationContext());
????????}
????????returnmRequestQueue;
????}
????public voidaddToRequestQueue(Request req, String tag) {
????????// set the default tag if tag is empty
????????req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
????????getRequestQueue().add(req);
????}
????public voidaddToRequestQueue(Request req) {
????????req.setTag(TAG);
????????getRequestQueue().add(req);
????}
????publicvoidcancelPendingRequests(Object tag) {
????????if(mRequestQueue != null) {
????????????mRequestQueue.cancelAll(tag);
????????}
????}
}
12。打開AndroidManifest.xml并將MyApplication添加到標(biāo)記晶渠。我們還需要INTERNET權(quán)限才能進(jìn)行http調(diào)用凰荚。
AndroidManifest.xml中
http://schemas.android.com/apk/res/android"
????package="info.androidhive.bottomnavigation">
????
????????android:name=".app.MyApplication"
????????android:allowBackup="true"
????????android:icon="@mipmap/ic_launcher"
????????android:label="@string/app_name"
????????android:roundIcon="@mipmap/ic_launcher_round"
????????android:supportsRtl="true"
????????android:theme="@style/AppTheme">
????????????android:name=".MainActivity"
????????????android:label="@string/app_name">
????????????
????????????????
????????????????
13。打開StoreFragment的布局文件褒脯,即fragment_store.xml便瑟,并添加下面的布局代碼。這里我們添加了RecyclerView組件憨颠。
fragment_store.xml
http://schemas.android.com/apk/res/android"
????xmlns:tools="http://schemas.android.com/tools"
????android:layout_width="match_parent"
????android:layout_height="match_parent"
????android:background="#f1f5f7"
????tools:context="info.androidhive.bottomnavigation.fragment.StoreFragment">
????????android:layout_width="match_parent"
????????android:layout_height="match_parent"
????????android:orientation="vertical">
????????????android:layout_width="match_parent"
????????????android:layout_height="wrap_content"
????????????android:paddingLeft="@dimen/activity_horizontal_margin"
????????????android:paddingTop="10dp"
????????????android:text="New Release Films"
????????????android:textColor="#111"
????????????android:textSize="16dp"/>
????????????android:id="@+id/recycler_view"
????????????android:layout_width="match_parent"
????????????android:layout_height="wrap_content"
????????????android:clipToPadding="false"
????????????android:scrollbars="vertical"/>
14胳徽。在res?布局下創(chuàng)建名為store_item_row.xml的xml?布局积锅。此布局文件將在RecyclerView適配器類中用于呈現(xiàn)單個(gè)項(xiàng)目。
store_item_row.xml
http://schemas.android.com/apk/res/android"
????xmlns:card_view="http://schemas.android.com/apk/res-auto"
????android:layout_width="match_parent"
????android:layout_height="wrap_content">
????????android:id="@+id/card_view"
????????android:layout_width="match_parent"
????????android:layout_height="match_parent"
????????android:layout_gravity="center"
????????android:layout_margin="@dimen/card_margin"
????????android:clickable="true"
????????android:elevation="3dp"
????????android:foreground="?attr/selectableItemBackground"
????????card_view:cardCornerRadius="@dimen/card_album_radius">
????????????android:layout_width="match_parent"
????????????android:layout_height="match_parent">
????????????????android:id="@+id/thumbnail"
????????????????android:layout_width="match_parent"
????????????????android:layout_height="@dimen/album_cover_height"
????????????????android:background="?attr/selectableItemBackgroundBorderless"
????????????????android:clickable="true"
????????????????android:scaleType="fitXY"/>
????????????????android:id="@+id/title"
????????????????android:layout_width="match_parent"
????????????????android:layout_height="wrap_content"
????????????????android:layout_below="@id/thumbnail"
????????????????android:lines="2"
????????????????android:paddingLeft="@dimen/album_title_padding"
????????????????android:paddingRight="@dimen/album_title_padding"
????????????????android:paddingTop="@dimen/album_title_padding"
????????????????android:textColor="#111"
????????????????android:textSize="11dp"/>
????????????????android:id="@+id/price"
????????????????android:layout_width="match_parent"
????????????????android:layout_height="wrap_content"
????????????????android:layout_below="@id/title"
????????????????android:layout_marginRight="10dp"
????????????????android:gravity="right"
????????????????android:paddingBottom="@dimen/songs_count_padding_bottom"
????????????????android:textColor="@color/colorAccent"
????????????????android:textSize="11dp"/>
15养盗。創(chuàng)建一個(gè)名為Movie.java的類缚陷。解析json時(shí),此POJO類將非常有用往核。
Movie.java
packageinfo.androidhive.bottomnavigation;
publicclassMovie {
????String title;
????String image;
????String price;
????publicString getTitle() {
????????returntitle;
????}
????publicvoidsetTitle(String title) {
????????this.title = title;
????}
????publicString getImage() {
????????returnimage;
????}
????publicvoidsetImage(String image) {
????????this.image = image;
????}
????publicString getPrice() {
????????returnprice;
????}
????publicvoidsetPrice(String price) {
????????this.price = price;
????}
}
16◇镆現(xiàn)在打開StoreFragment.java并添加下面的代碼。為簡(jiǎn)單起見聂儒,RecyclerView適配器類StoreAdapter包含在同一個(gè)片段中虎锚。
>?fetchStoreItems()方法使用Volley獲取電影json并使用Gson對(duì)其進(jìn)行序列化。
>?StoreAdapter類在RecyclerView中呈現(xiàn)電影衩婚。
StoreFragment.java
packageinfo.androidhive.bottomnavigation.fragment;
importandroid.content.Context;
importandroid.content.res.Resources;
importandroid.graphics.Rect;
importandroid.os.Bundle;
importandroid.support.v4.app.Fragment;
importandroid.support.v7.widget.DefaultItemAnimator;
importandroid.support.v7.widget.GridLayoutManager;
importandroid.support.v7.widget.RecyclerView;
importandroid.util.Log;
importandroid.util.TypedValue;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ImageView;
importandroid.widget.TextView;
importandroid.widget.Toast;
importcom.android.volley.Response;
importcom.android.volley.VolleyError;
importcom.android.volley.toolbox.JsonArrayRequest;
importcom.bumptech.glide.Glide;
importcom.google.gson.Gson;
importcom.google.gson.reflect.TypeToken;
importorg.json.JSONArray;
importjava.util.ArrayList;
importjava.util.List;
importinfo.androidhive.bottomnavigation.Movie;
importinfo.androidhive.bottomnavigation.app.MyApplication;
importinfo.androidhive.bottomnavigation.R;
publicclassStoreFragment extendsFragment {
????privatestaticfinalString TAG = StoreFragment.class.getSimpleName();
????privatestaticfinalString URL = "https://api.androidhive.info/json/movies_2017.json";
????privateRecyclerView recyclerView;
????privateList movieList;
????privateStoreAdapter mAdapter;
????publicStoreFragment() {
????????// Required empty public constructor
????}
????publicstaticStoreFragment newInstance(String param1, String param2) {
????????StoreFragment fragment = newStoreFragment();
????????Bundle args = newBundle();
????????fragment.setArguments(args);
????????returnfragment;
????}
????@Override
????publicvoidonCreate(Bundle savedInstanceState) {
????????super.onCreate(savedInstanceState);
????}
????@Override
????publicView onCreateView(LayoutInflater inflater, ViewGroup container,
?????????????????????????????Bundle savedInstanceState) {
????????// Inflate the layout for this fragment
????????View view = inflater.inflate(R.layout.fragment_store, container, false);
????????recyclerView = view.findViewById(R.id.recycler_view);
????????movieList = newArrayList<>();
????????mAdapter = newStoreAdapter(getActivity(), movieList);
????????RecyclerView.LayoutManager mLayoutManager = newGridLayoutManager(getActivity(), 3);
????????recyclerView.setLayoutManager(mLayoutManager);
????????recyclerView.addItemDecoration(newGridSpacingItemDecoration(2, dpToPx(8), true));
????????recyclerView.setItemAnimator(newDefaultItemAnimator());
????????recyclerView.setAdapter(mAdapter);
????????recyclerView.setNestedScrollingEnabled(false);
????????fetchStoreItems();
????????returnview;
????}
????privatevoidfetchStoreItems() {
????????JsonArrayRequest request = newJsonArrayRequest(URL,
????????????????newResponse.Listener() {
????????????????????@Override
????????????????????publicvoidonResponse(JSONArray response) {
????????????????????????if(response == null) {
????????????????????????????Toast.makeText(getActivity(), "Couldn't fetch the store items! Pleas try again.", Toast.LENGTH_LONG).show();
????????????????????????????return;
????????????????????????}
????????????????????????List items = newGson().fromJson(response.toString(), newTypeToken>() {
????????????????????????}.getType());
????????????????????????movieList.clear();
????????????????????????movieList.addAll(items);
????????????????????????// refreshing recycler view
????????????????????????mAdapter.notifyDataSetChanged();
????????????????????}
????????????????}, newResponse.ErrorListener() {
????????????@Override
????????????publicvoidonErrorResponse(VolleyError error) {
????????????????// error in getting json
????????????????Log.e(TAG, "Error: "+ error.getMessage());
????????????????Toast.makeText(getActivity(), "Error: "+ error.getMessage(), Toast.LENGTH_SHORT).show();
????????????}
????????});
????????MyApplication.getInstance().addToRequestQueue(request);
????}
????publicclassGridSpacingItemDecoration extendsRecyclerView.ItemDecoration {
????????privateintspanCount;
????????privateintspacing;
????????privatebooleanincludeEdge;
????????publicGridSpacingItemDecoration(intspanCount, intspacing, booleanincludeEdge) {
????????????this.spanCount = spanCount;
????????????this.spacing = spacing;
????????????this.includeEdge = includeEdge;
????????}
????????@Override
????????publicvoidgetItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
????????????intposition = parent.getChildAdapterPosition(view); // item position
????????????intcolumn = position % spanCount; // item column
????????????if(includeEdge) {
????????????????outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
????????????????outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
????????????????if(position < spanCount) { // top edge
????????????????????outRect.top = spacing;
????????????????}
????????????????outRect.bottom = spacing; // item bottom
????????????} else{
????????????????outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
????????????????outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /??? spanCount) * spacing)
????????????????if(position >= spanCount) {
????????????????????outRect.top = spacing; // item top
????????????????}
????????????}
????????}
????}
????/**
?????* Converting dp to pixel
?????*/
????privateintdpToPx(intdp) {
????????Resources r = getResources();
????????returnMath.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
????}
????classStoreAdapter extendsRecyclerView.Adapter {
????????privateContext context;
????????privateList movieList;
????????publicclassMyViewHolder extendsRecyclerView.ViewHolder {
????????????publicTextView name, price;
????????????publicImageView thumbnail;
????????????publicMyViewHolder(View view) {
????????????????super(view);
????????????????name = view.findViewById(R.id.title);
????????????????price = view.findViewById(R.id.price);
????????????????thumbnail = view.findViewById(R.id.thumbnail);
????????????}
????????}
????????publicStoreAdapter(Context context, List movieList) {
????????????this.context = context;
????????????this.movieList = movieList;
????????}
????????@Override
????????publicMyViewHolder onCreateViewHolder(ViewGroup parent, intviewType) {
????????????View itemView = LayoutInflater.from(parent.getContext())
????????????????????.inflate(R.layout.store_item_row, parent, false);
????????????returnnewMyViewHolder(itemView);
????????}
????????@Override
????????publicvoidonBindViewHolder(MyViewHolder holder, finalintposition) {
????????????finalMovie movie = movieList.get(position);
????????????holder.name.setText(movie.getTitle());
????????????holder.price.setText(movie.getPrice());
????????????Glide.with(context)
????????????????????.load(movie.getImage())
????????????????????.into(holder.thumbnail);
????????}
????????@Override
????????publicintgetItemCount() {
????????????returnmovieList.size();
????????}
????}
}
現(xiàn)在窜护,如果您運(yùn)行該應(yīng)用程序,您可以看到ShopFragment以網(wǎng)格方式顯示電影非春。同樣柱徙,您也可以實(shí)現(xiàn)其他片段。
5.在滾動(dòng)條上隱藏底部導(dǎo)航
根據(jù)設(shè)計(jì)規(guī)范奇昙,滾動(dòng)內(nèi)容時(shí)必須隱藏底部導(dǎo)航护侮,從而為屏幕上的內(nèi)容提供更多空間。為此储耐,我們需要將BottomNavigationBehavior附加到底部導(dǎo)航羊初。
17。使用以下代碼創(chuàng)建名為BottomNavigationBehavior.java的類什湘。
BottomNavigationBehavior.java
packageinfo.androidhive.bottomnavigation.helper;
importandroid.content.Context;
importandroid.support.design.widget.BottomNavigationView;
importandroid.support.design.widget.CoordinatorLayout;
importandroid.support.v4.view.ViewCompat;
importandroid.util.AttributeSet;
importandroid.view.View;
importandroid.widget.FrameLayout;
publicclassBottomNavigationBehavior extendsCoordinatorLayout.Behavior {
????publicBottomNavigationBehavior() {
????????super();
????}
????publicBottomNavigationBehavior(Context context, AttributeSet attrs) {
????????super(context, attrs);
????}
????@Override
????publicbooleanlayoutDependsOn(CoordinatorLayout parent, BottomNavigationView child, View dependency) {
????????booleandependsOn = dependency instanceofFrameLayout;
????????returndependsOn;
????}
????@Override
????publicbooleanonStartNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View directTargetChild, View target, intnestedScrollAxes) {
????????returnnestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
????}
????@Override
????publicvoidonNestedPreScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View target, intdx, intdy, int[] consumed) {
????????if(dy < 0) {
????????????showBottomNavigationView(child);
????????} elseif(dy > 0) {
????????????hideBottomNavigationView(child);
????????}
????}
????privatevoidhideBottomNavigationView(BottomNavigationView view) {
????????view.animate().translationY(view.getHeight());
????}
????privatevoidshowBottomNavigationView(BottomNavigationView view) {
????????view.animate().translationY(0);
????}
}
18长赞。添加BottomNavigationBehavior使用setBehavior()在MainActivity.java如下所示。
MainActivity.java
publicclassMainActivity extendsAppCompatActivity {
????privateActionBar toolbar;
????@Override
????protectedvoidonCreate(Bundle savedInstanceState) {
????????super.onCreate(savedInstanceState);
????????setContentView(R.layout.activity_main);
????????BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
????????navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
????????// attaching bottom sheet behaviour - hide / show on scroll
????????CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) navigation.getLayoutParams();
????????layoutParams.setBehavior(newBottomNavigationBehavior());
????????// load the store fragment by default
????????// ..
????}
}
現(xiàn)在禽炬,如果您測(cè)試應(yīng)用程序涧卵,則可以在滾動(dòng)應(yīng)用程序內(nèi)容時(shí)看到底部導(dǎo)航向下滑動(dòng)勤家。