下载地址:https://pan.baidu.com/s/1_1x0nBdv8_QgEgnveOZEZw
CardView是Material Design中引入的另一个主要元素。使用CardView,您可以以卡片方式表示信息,其中阴影(仰角)和角半径在整个平台上看起来是一致的。CardView扩展了FrameLayout,并支持返回Android 2.x.
当CardView与RecyclerView结合使用时,您可以获得美观的UI。在本文中,我们将学习如何通过创建一个漂亮的音乐应用程序来集成CardView和RecyclerView,该应用程序显示带有封面图像和标题的音乐专辑。
视频演示
如何添加CardView?
要在应用程序中使用CardView,请在build.gradle中添加CardView依赖项并同步项目。
的build.gradle
dependencies {
// CardView
compile 'com.android.support:cardview-v7:23.3.+'
}
将小部件添加到您的布局中,并将其他UI小部件(如TextViews,ImageViews)放入其中。您可以注意到,下面的CardView小部件包含一个TextView。
http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto">
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="250dp"
android:layout_height="250dp"
card_view:cardCornerRadius="4dp">
android:text="Hello Card"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
现在让我们通过创建一个新项目来实现这一点。
1.创建新项目
1。从File⇒NewProject在Android Studio中创建一个新项目。当它提示您选择默认活动时,请选择清空活动并继续。
2。下载此res.zip并将其添加到您的项目res文件夹中。此res文件夹包含此项目所需的几个专辑封面和图标。
3。将以下字符串,颜色和维度资源添加到strings.xml,colors.xml和dimens.xml文件中。
strings.xml中
Card View
Settings
Add to Favourites
Play Next
LOVE MUSIC
This season top 20 albums
colors.xml
#F50057
#F50057
#FF4081
#f1f5f8
#4c4c4c
dimens.xml
16dp
16dp
16dp
10dp
250dp
30dp
18dp
5dp
0dp
160dp
10dp
15dp
5dp
12dp
20dp
30dp
10dp
4。打开build.gradle并添加CardView,RecyclerView和Glide依赖项。RecyclerView用于以网格方式显示相册。CardView用于显示单个专辑项目。Glide用于显示专辑封面图像。
的build.gradle
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
// RecyclerView
compile 'com.android.support:recyclerview-v7:23.3.+'
// CardView
compile 'com.android.support:cardview-v7:23.3.+'
// Glide
compile 'com.github.bumptech.glide:glide:3.7.0'
}
5。要创建单个专辑的实例,我们需要一个表示专辑属性的模型类,如名称,歌曲数量和封面图像。因此,创建一个名为Album.java的类并添加以下代码。
Album.java
packageinfo.androidhive.cardview;
/**
* Created by Lincoln on 18/05/16.
*/
publicclassAlbum {
privateString name;
privateintnumOfSongs;
privateintthumbnail;
publicAlbum() {
}
publicAlbum(String name, intnumOfSongs, intthumbnail) {
this.name = name;
this.numOfSongs = numOfSongs;
this.thumbnail = thumbnail;
}
publicString getName() {
returnname;
}
publicvoidsetName(String name) {
this.name = name;
}
publicintgetNumOfSongs() {
returnnumOfSongs;
}
publicvoidsetNumOfSongs(intnumOfSongs) {
this.numOfSongs = numOfSongs;
}
publicintgetThumbnail() {
returnthumbnail;
}
publicvoidsetThumbnail(intthumbnail) {
this.thumbnail = thumbnail;
}
}
6。我们还需要一个xm布局来显示相册卡。在res⇒布局下创建名为album_card.xml的xml布局。在这里您可以注意到我添加了并添加了所有相册属性,如名称,歌曲数量和封面图像。我还添加了一个3点图标,在点击它时会显示一个弹出菜单。
album_card.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:elevation="3dp"
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: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"/>
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"/>
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"/>
7。在res⇒ 菜单文件夹下创建一个名为menu_album.xml的菜单文件。点击每个相册卡片项目上的圆点图标,此菜单将显示为弹出菜单。
menu_album.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/action_add_favourite"
android:orderInCategory="100"
android:title="@string/action_add_favourite"/>
android:id="@+id/action_play_next"
android:orderInCategory="101"
android:title="@string/action_play_next"/>
8。要呈现RecyclerView,我们需要一个适配器类,通过保留适当的信息来扩充album_card.xml。创建一个名为AlbumsAdapter.java的类并添加以下内容。
AlbumsAdapter.java
packageinfo.androidhive.cardview;
importandroid.content.Context;
importandroid.support.v7.widget.PopupMenu;
importandroid.support.v7.widget.RecyclerView;
importandroid.view.LayoutInflater;
importandroid.view.MenuInflater;
importandroid.view.MenuItem;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ImageView;
importandroid.widget.TextView;
importandroid.widget.Toast;
importcom.bumptech.glide.Glide;
importjava.util.List;
/**
* Created by Ravi Tamada on 18/05/16.
*/
publicclassAlbumsAdapter extendsRecyclerView.Adapter {
privateContext mContext;
privateList albumList;
publicclassMyViewHolder extendsRecyclerView.ViewHolder {
publicTextView title, count;
publicImageView thumbnail, overflow;
publicMyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
count = (TextView) view.findViewById(R.id.count);
thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
overflow = (ImageView) view.findViewById(R.id.overflow);
}
}
publicAlbumsAdapter(Context mContext, List albumList) {
this.mContext = mContext;
this.albumList = albumList;
}
@Override
publicMyViewHolder onCreateViewHolder(ViewGroup parent, intviewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.album_card, parent, false);
returnnewMyViewHolder(itemView);
}
@Override
publicvoidonBindViewHolder(finalMyViewHolder holder, intposition) {
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(newView.OnClickListener() {
@Override
publicvoidonClick(View view) {
showPopupMenu(holder.overflow);
}
});
}
/**
* Showing popup menu when tapping on 3 dots
*/
privatevoidshowPopupMenu(View view) {
// inflate menu
PopupMenu popup = newPopupMenu(mContext, view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_album, popup.getMenu());
popup.setOnMenuItemClickListener(newMyMenuItemClickListener());
popup.show();
}
/**
* Click listener for popup menu items
*/
classMyMenuItemClickListener implementsPopupMenu.OnMenuItemClickListener {
publicMyMenuItemClickListener() {
}
@Override
publicbooleanonMenuItemClick(MenuItem menuItem) {
switch(menuItem.getItemId()) {
caseR.id.action_add_favourite:
Toast.makeText(mContext, "Add to favourite", Toast.LENGTH_SHORT).show();
returntrue;
caseR.id.action_play_next:
Toast.makeText(mContext, "Play next", Toast.LENGTH_SHORT).show();
returntrue;
default:
}
returnfalse;
}
}
@Override
publicintgetItemCount() {
returnalbumList.size();
}
}
9。打开布局文件主要活动activity_main.xml和content_main.xml,添加AppBarLayout,CollapsingToolbarLayout,Toolbar和RecyclerView。
activity_main.xml中
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: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: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">
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
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"/>
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"/>
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
content_main.xml
content_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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/viewBg"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="info.androidhive.cardview.MainActivity"
tools:showIn="@layout/activity_main">
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollbars="vertical"/>
10。最后打开MainActivity.java并进行必要的更改。
> initCollapsingToolbar()- 在折叠或展开工具栏时显示或隐藏工具栏标题。
> prepareAlbums()- 添加回收站视图所需的样本专辑数据。
> GridLayoutManager用于以网格方式而不是列表显示RecyclerView。
> GridSpacingItemDecoration用于在RecyclerView网格项周围提供相等的边距。
> AlbumsAdapter实例已创建并分配给RecyclerView,后者以网格方式呈现CardView相册。
MainActivity.java
packageinfo.androidhive.cardview;
importandroid.content.res.Resources;
importandroid.graphics.Rect;
importandroid.os.Bundle;
importandroid.support.design.widget.AppBarLayout;
importandroid.support.design.widget.CollapsingToolbarLayout;
importandroid.support.v7.app.AppCompatActivity;
importandroid.support.v7.widget.DefaultItemAnimator;
importandroid.support.v7.widget.GridLayoutManager;
importandroid.support.v7.widget.RecyclerView;
importandroid.support.v7.widget.Toolbar;
importandroid.util.TypedValue;
importandroid.view.View;
importandroid.widget.ImageView;
importcom.bumptech.glide.Glide;
importjava.util.ArrayList;
importjava.util.List;
publicclassMainActivity extendsAppCompatActivity {
privateRecyclerView recyclerView;
privateAlbumsAdapter adapter;
privateList albumList;
@Override
protectedvoidonCreate(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 = newArrayList<>();
adapter = newAlbumsAdapter(this, albumList);
RecyclerView.LayoutManager mLayoutManager = newGridLayoutManager(this, 2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(newGridSpacingItemDecoration(2, dpToPx(10), true));
recyclerView.setItemAnimator(newDefaultItemAnimator());
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
*/
privatevoidinitCollapsingToolbar() {
finalCollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(" ");
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
appBarLayout.setExpanded(true);
// hiding & showing the title when toolbar expanded & collapsed
appBarLayout.addOnOffsetChangedListener(newAppBarLayout.OnOffsetChangedListener() {
booleanisShow = false;
intscrollRange = -1;
@Override
publicvoidonOffsetChanged(AppBarLayout appBarLayout, intverticalOffset) {
if(scrollRange == -1) {
scrollRange = appBarLayout.getTotalScrollRange();
}
if(scrollRange + verticalOffset == 0) {
collapsingToolbar.setTitle(getString(R.string.app_name));
isShow = true;
} elseif(isShow) {
collapsingToolbar.setTitle(" ");
isShow = false;
}
}
});
}
/**
* Adding few albums for testing
*/
privatevoidprepareAlbums() {
int[] covers = newint[]{
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 = newAlbum("True Romance", 13, covers[0]);
albumList.add(a);
a = newAlbum("Xscpae", 8, covers[1]);
albumList.add(a);
a = newAlbum("Maroon 5", 11, covers[2]);
albumList.add(a);
a = newAlbum("Born to Die", 12, covers[3]);
albumList.add(a);
a = newAlbum("Honeymoon", 14, covers[4]);
albumList.add(a);
a = newAlbum("I Need a Doctor", 1, covers[5]);
albumList.add(a);
a = newAlbum("Loud", 11, covers[6]);
albumList.add(a);
a = newAlbum("Legend", 14, covers[7]);
albumList.add(a);
a = newAlbum("Hello", 11, covers[8]);
albumList.add(a);
a = newAlbum("Greatest Hits", 17, covers[9]);
albumList.add(a);
adapter.notifyDataSetChanged();
}
/**
* RecyclerView item decoration - give equal margin around grid item
*/
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()));
}
}
如果您现在运行该应用程序,您可以看到网格中显示的专辑CardViews。
你好!我是androidhive和编程爱好者的创始人。我的技能包括Android,iOS,PHP,Ruby on Rails等等。如果您有任何想法,我希望我发展?我们来聊聊吧:ravi@androidhive.info