build.gradle (Module.app)
添加CardView,RecyclerView和Glide依賴關係。- RecyclerView用於以網格方式顯示相冊。
- CardView用於顯示單個專輯項目。
- Glide用於顯示專輯封面圖片。
dependencies {
//CardView
compile 'com.android.support:cardview-v7:25.3.1'
//RecyclerView
compile 'com.android.support:recyclerview-v7:25.3.1'
//Glide ImageLoader....
compile 'com.github.bumptech.glide:glide:3.7.0'
}
將以下字符串,顏色和調整資源添加到strings.xml,colors.xml和dimensions.xml文件。
string.xml
<resources>
<string name="app_name">Card View</string>
<string name="action_settings">Settings</string>
<string name="action_add_favourite">Add to Favourites</string>
<string name="action_play_next">Play Next</string>
<string name="backdrop_title">LOVE MUSIC</string>
<string name="backdrop_subtitle">This season top 20 albums</string>
</resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#F50057</color>
<color name="colorPrimaryDark">#F50057</color>
<color name="colorAccent">#FF4081</color>
<color name="viewBg">#f1f5f8</color>
<color name="album_title">#4c4c4c</color>
</resources>
dimensions.xml
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="item_offset">10dp</dimen>
<dimen name="detail_backdrop_height">250dp</dimen>
<dimen name="backdrop_title">30sp</dimen>
<dimen name="backdrop_subtitle">18sp</dimen>
<dimen name="card_margin">5dp</dimen>
<dimen name="card_album_radius">0dp</dimen>
<dimen name="album_cover_height">160dp</dimen>
<dimen name="album_title_padding">10dp</dimen>
<dimen name="album_title">15dp</dimen>
<dimen name="songs_count_padding_bottom">5dp</dimen>
<dimen name="songs_count">12sp</dimen>
<dimen name="ic_album_overflow_width">20dp</dimen>
<dimen name="ic_album_overflow_height">30dp</dimen>
<dimen name="ic_album_overflow_margin_top">10dp</dimen>
</resources>
創建一個名為Album.java的類並添加以下代碼:
/**
* Created by claire on 2017/10/12.
* Album 專輯
*/
public class Album {
private String name;
private int numOfSongs;
private int thumbnail; //縮圖
public Album(){
}
public Album(String name, int numOfSongs, int thumbnail) {
this.name = name;
this.numOfSongs = numOfSongs;
this.thumbnail = thumbnail;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumOfSongs() {
return numOfSongs;
}
public void setNumOfSongs(int numOfSongs) {
this.numOfSongs = numOfSongs;
}
public int getThumbnail() {
return thumbnail;
}
public void setThumbnail(int thumbnail) {
this.thumbnail = thumbnail;
}
}
新增一個xm佈局來顯示專輯相冊。
1.在res⇒佈局下創建名為album_card.xml的xml佈局。
2.添加<android.support.v7.widget.CardView>,並添加了所有的相冊屬性, 如名稱,歌曲數量和封面圖像。
3.還添加了一個3點圖標,顯示一個彈出菜單點擊它。
<LinearLayout xmlns:android="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.support.v7.widget.CardView
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:elevation="3dp"
card_view:cardCornerRadius="@dimen/card_album_radius">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
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" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/thumbnail"
android:paddingLeft="@dimen/album_title_padding"
android:paddingRight="@dimen/album_title_padding"
android:paddingTop="@dimen/album_title_padding"
android:textColor="@color/album_title"
android:textSize="@dimen/album_title" />
<TextView
android:id="@+id/count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:paddingBottom="@dimen/songs_count_padding_bottom"
android:paddingLeft="@dimen/album_title_padding"
android:paddingRight="@dimen/album_title_padding"
android:textSize="@dimen/songs_count" />
<ImageView
android:id="@+id/overflow"
android:layout_width="@dimen/ic_album_overflow_width"
android:layout_height="@dimen/ic_album_overflow_height"
android:layout_alignParentRight="true"
android:layout_below="@id/thumbnail"
android:layout_marginTop="@dimen/ic_album_overflow_margin_top"
android:scaleType="centerCrop"
android:src="@drawable/ic_dots" />
</RelativeLayout
</android.support.v7.widget.CardView>
</LinearLayout>
在res⇒menu folder下創建名為menu_album.xml的菜單文件。
點擊每張專輯卡片上的點圖標,此菜單將顯示為彈出菜單。
menu_album.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/action_add_favourite"
android:orderInCategory="100"
android:title="@string/action_add_favourite" />
<item
android:id="@+id/action_play_next"
android:orderInCategory="101"
android:title="@string/action_play_next" />
</menu>
為RecyclerView添加一個適配器 AlbumsAdapter.java,
album_card.xml來顯示內容
public class AlbumsAdapter extends RecyclerView.Adapter<AlbumsAdapter.MyViewHolder>{
private Context mContext;
private List<Album> albumList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, count;
public ImageView thumbnail, overflow;
public MyViewHolder(View itemView) {
super(itemView);
title = (TextView)itemView.findViewById(R.id.title);
count = (TextView)itemView.findViewById(R.id.count);
thumbnail = (ImageView)itemView.findViewById(R.id.thumbnail);
overflow = (ImageView)itemView.findViewById(R.id.overflow);
}
}
public AlbumsAdapter (Context mContext, List<Album> albumList){
this.mContext = mContext;
this.albumList = albumList;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.album_card, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
Album album = albumList.get(position);
holder.title.setText(album.getName());
holder.count.setText(album.getNumOfSongs() + " songs");
//loading album cover using Glide library
Glide.with(mContext).load(album.getThumbnail()).into(holder.thumbnail);
holder.overflow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPopupMenu(holder.overflow);
}
});
}
/**
* Showing popup menu when tapping on 3 dots
* @param view
* Android 作業系統中,彈出式選單(PopupMenu)只能依附在 View 型別之物件
*/
private void showPopupMenu(View view) {
//inflate menu
PopupMenu popup = new PopupMenu(mContext, view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_album, popup.getMenu());
popup.setOnMenuItemClickListener(new MymenuItemClickListener());
popup.show();
}
/**
* Click listener for popup menu items
*/
class MymenuItemClickListener implements PopupMenu.OnMenuItemClickListener{
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.action_add_favourite:
Toast.makeText(mContext, "Add to favorite", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_play_next:
Toast.makeText(mContext, "Play next", Toast.LENGTH_SHORT).show();
return true;
default:
}
return false;
}
}
@Override
public int getItemCount() {
return albumList.size();
}
}
開啟 main activity activity_main.xml and content_main.xml,
加上 AppBarLayout, CollapsingToolbarLayout, Toolbar and RecyclerView
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:expandedTitleTextAppearance="@android:color/transparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/love_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/backdrop_title"
android:textColor="@android:color/white"
android:textSize="@dimen/backdrop_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/backdrop_subtitle"
android:textColor="@android:color/white"
android:textSize="@dimen/backdrop_subtitle" />
</LinearLayout>
</RelativeLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main"/>
</android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/viewBg"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.admin.claire.cardviewandrecyclerview.MainActivity"
tools:showIn="@layout/activity_main">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollbars="vertical" />
</RelativeLayout>
最後打開 MainActivity.java 並進行必要的
- initCollapsingToolbar()-當工具欄折疊或展開時顯示或隱藏工具欄標題
- prepareAlbums() – Adds sample albums data required for the recycler view.
- GridLayoutManager用於以Grid格式顯示RecyclerView而不是列表。
- GridSpacingItemDecoration用於在RecyclerView網格項周圍給出相等的邊距。
- AlbumAdapter實例被創建並分配給RecyclerView,它以網格方式呈現CardView專輯。
package com.admin.claire.cardviewandrecyclerview;
import android.content.res.Resources;
import android.graphics.Rect;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private AlbumsAdapter adapter;
private List<Album> albumList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initCollapsingToolbar();
recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
albumList = new ArrayList<>();
adapter = new AlbumsAdapter(this, albumList);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(mLayoutManager);
//RecyclerView項目裝飾 - 在網格項目周圍給予相等的邊距
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2,dpToPx(10),true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
prepareAlbums();
try{
Glide.with(this).load(R.drawable.cover)
.into((ImageView)findViewById(R.id.backdrop));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* Initializing collapsing toolbar
* Will show and hide the toolbar title on scroll
*/
private void initCollapsingToolbar() {
final CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout)findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("");
AppBarLayout appBarLayout = (AppBarLayout)findViewById(R.id.appbar);
appBarLayout.setExpanded(true);
//隱藏並顯示工具欄,展開和折疊時的標題
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isShow = false;
int scrollRange = -1;
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (scrollRange == -1){
scrollRange = appBarLayout.getTotalScrollRange();
}
if (scrollRange + verticalOffset == 0){
collapsingToolbar.setTitle(getString(R.string.app_name));
isShow = true;
} else if(isShow){
collapsingToolbar.setTitle("");
isShow = false;
}
}
});
}
/**
* Adding few albums for testing
*/
private void prepareAlbums() {
int[] covers = new int[]{
R.drawable.album1,
R.drawable.album2,
R.drawable.album3,
R.drawable.album4,
R.drawable.album5,
R.drawable.album6,
R.drawable.album7,
R.drawable.album8,
R.drawable.album9,
R.drawable.album10,
R.drawable.album11};
Album a = new Album("True Romance", 13, covers[0]);
albumList.add(a);
a = new Album("Xscpae", 8, covers[1]);
albumList.add(a);
a = new Album("Maroon 5", 11, covers[2]);
albumList.add(a);
a = new Album("Born to Die", 12, covers[3]);
albumList.add(a);
a = new Album("Honeymoon", 14, covers[4]);
albumList.add(a);
a = new Album("I Need a Doctor", 1, covers[5]);
albumList.add(a);
a = new Album("Loud", 11, covers[6]);
albumList.add(a);
a = new Album("Legend", 14, covers[7]);
albumList.add(a);
a = new Album("Hello", 11, covers[8]);
albumList.add(a);
a = new Album("Greatest Hits", 17, covers[9]);
albumList.add(a);
adapter.notifyDataSetChanged();
}
/**
* RecyclerView項目裝飾 - 在網格項目周圍給予相等的邊距
*/
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration{
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); //item position
int column = position % spanCount; //item column
if (includeEdge){
// spacing - column * ((1f / spanCount) * spacing)
outRect.left = spacing - column * spacing / spanCount;
// (column + 1) * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount;
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 將dp轉換為像素
*/
private int dpToPx(int dp) {
Resources r = getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
}
style.xml
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
AndroidManifest.xml
android:theme="@style/AppTheme.NoActionBar"
留言
張貼留言