Android working with Card View and Recycler View
1. Giới thiệu CardView là thành phần được giới thiệu trong Material Design. Dùng CardView ta có thể hiển thị thông tin trong thẻ với độ chân thực cao hơn như một vật thể ngoài đời thực như có hiệu ứng đổ bóng và bo tròn các góc của thẻ. CardView thường được dùng với RecyclerView để tạo ...
1. Giới thiệu
CardView là thành phần được giới thiệu trong Material Design. Dùng CardView ta có thể hiển thị thông tin trong thẻ với độ chân thực cao hơn như một vật thể ngoài đời thực như có hiệu ứng đổ bóng và bo tròn các góc của thẻ.
CardView thường được dùng với RecyclerView để tạo được hiệu quả tốt nhất về UI gây ấn tượng cho người dùng.
để biết thêm về CardView cũng như RecyclerView bạn có thể tìm thêm thông tin tại đây
2. Làm thế nào để thêm CardView
Để dùng CardView ta thêm dòng sau vào dependency trong build.gradle và Sync project
build.gradle dependencies { // CardView compile 'com.android.support:cardview-v7:23.3.+' }
Sau đó thêm <android.support.v7.widget.CardView> vào layout, tiếp theo ta thêm các widget vào trong tag trên.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:card_view="http://schemas.android.com/apk/res-auto"> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_gravity="center" android:layout_awidth="250dp" android:layout_height="250dp" card_view:cardCornerRadius="4dp"> <TextView android:text="Hello Card" android:layout_awidth="match_parent" android:layout_height="match_parent" /> </android.support.v7.widget.CardView> </LinearLayout>
Bây giờ ta sẽ tạo project và thêm các thuộc tính và layout trên vào project
3. Tạo Project
Thêm các Resource sau vào project
strings.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>
dimens.xml <resources> <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">30dp</dimen> <dimen name="backdrop_subtitle">18dp</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">12dp</dimen> <dimen name="ic_album_overflow_awidth">20dp</dimen> <dimen name="ic_album_overflow_height">30dp</dimen> <dimen name="ic_album_overflow_margin_top">10dp</dimen> </resources>
Tiếp theo mở file build.gradle và thêm CardView, RecyclerView, Glide. RecyclerView dùng để hiển thị album dưới dạng grid, CardView dùng để hiển thị mỗi album. Glide để hiển thị ảnh của album.
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' }
để hiển thị một album ta sẽ tạo model Album.java
Album.java 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; } }
Tiếp theo tạo layout hiển thị album card. Tạo 1 file xml album_card.xml
album_card.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_awidth="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_awidth="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_awidth="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/thumbnail" android:layout_awidth="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_awidth="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_awidth="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_awidth="@dimen/ic_album_overflow_awidth" 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>
Tạo file menu_album.xml dưới folder res => menu. Menu này sẽ hiển thị khi người dùng tab vào dấu 3 chấm trên mỗi album card.
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>
Cuối cùng để hiển thị thông tin album trên mỗi cardview ta cần một adapter để RecyclerView có thể hiển thị thông tin. Ta tạo AlbumsAdapter.java
AlbumsAdapter.java 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 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); } } public AlbumsAdapter(Context mContext, List<Album> albumList) { this.mContext = mContext; this.albumList = albumList; } public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.album_card, parent, false); return new MyViewHolder(itemView); } 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() { public void onClick(View view) { showPopupMenu(holder.overflow); } }); } /** * Showing popup menu when tapping on 3 dots */ 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 { public MyMenuItemClickListener() { } public boolean onMenuItemClick(MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.action_add_favourite: Toast.makeText(mContext, "Add to favourite", 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; } } public int getItemCount() { return albumList.size(); } }
Tiếp theo ta sửa lại file layout của MainActivity
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_awidth="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_awidth="match_parent" android:layout_heig