一、CardView
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" app:cardCornerRadius="4dp"> <TextView android:id="@+id/overwatch_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_margin="5dp" android:textSize="16sp"/> </android.support.v7.widget.CardView>
這是一個CardView的簡單布局,app:cardCornerRadius這個屬性指定了卡片圓角的弧度,另外還可以通過app:elevation指定卡片的高度,改變卡片的陰影效果。
要使用CardView需要添加相應的庫,在app/build.gradle中:
compile 'com.android.support:recyclerview-v7:26.+' compile 'com.android.support:cardview-v7:26.+' compile 'com.github.bumptech.glide:glide:4.0.0'
第一行是RecyclerView需要的庫,第二行就是CardView,第三行是一個Glide的庫,Glide是一個超級強大的圖片加載庫,一行代碼就能實現圖片加載功能。
首先在主活動的布局中加入RecyclerView:
<android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_height="match_parent" android:layout_width="match_parent" />
然后為RecyclerView的子項指定一個自定義的布局,在layout目錄下新建overwatch_item.xml:
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" app:cardCornerRadius="4dp"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/overwatch_image" android:layout_width="match_parent" android:layout_height="100dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/overwatch_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_margin="5dp" android:textSize="16sp"/> </LinearLayout> </android.support.v7.widget.CardView>
然后新建一個OverWatch類:
public class OverWatch { private String name; private int imageID; public OverWatch(String name, int imageID) { this.imageID = imageID; this.name = name; } public String getName() { return name; } public int getImageID() { return imageID; } }
這個類就是每個卡片的內容了。name代表名字,imageID代表圖片資源ID。
然后就需要為RecyclerView准備一個適配器:
1 public class OverWatchAdapter extends RecyclerView.Adapter<OverWatchAdapter.ViewHolder> { 2 3 private Context mContext; 4 5 private List<OverWatch> mOverWatch; 6 7 static class ViewHolder extends RecyclerView.ViewHolder{ 8 9 CardView cardView; 10 ImageView overwatchImage; 11 TextView overwatchName; 12 13 public ViewHolder(View view){ 14 super(view); 15 cardView = (CardView) view; 16 overwatchImage = (ImageView) view.findViewById(R.id.overwatch_image); 17 overwatchName = (TextView) view.findViewById(R.id.overwatch_name); 18 } 19 } 20 21 public OverWatchAdapter(List<OverWatch> OverWatchList){ 22 mOverWatch = OverWatchList; 23 } 24 25 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 26 if(mContext == null){ 27 mContext = parent.getContext(); 28 } 29 View view = LayoutInflater.from(mContext).inflate(R.layout.overwatch_item,parent,false); 30 return new ViewHolder(view); 31 } 32 public void onBindViewHolder(ViewHolder viewHolder, int position) { 33 OverWatch overWatch = mOverWatch.get(position); 34 viewHolder.overwatchName.setText(overWatch.getName()); 35 Glide.with(mContext).load(overWatch.getImageID()).into(viewHolder.overwatchImage); 36 } 37 38 public int getItemCount() { 39 return mOverWatch.size(); 40 } 41 }
第35行就是Glide加載圖片的方法,首先是調用Glide.with()方法傳入一個Context參數,然后調用load()方法去加載圖片,參數可以是URI,也可以使一個本地路徑,或者是一個資源ID,然后再調用into()方法將圖片設置到某一個ImageView中去。
然后就是主活動的java代碼:
1 public class MainActivity extends AppCompatActivity { 2 3 private DrawerLayout mDrawerLayout; 4 5 private OverWatch[] overWatches = {new OverWatch("獵空",R.drawable.img_1),new OverWatch("獵空",R.drawable.img_2), 6 new OverWatch("獵空",R.drawable.img_3),new OverWatch("獵空",R.drawable.img_5), 7 new OverWatch("獵空",R.drawable.img_6),new OverWatch("獵空",R.drawable.img_7), 8 new OverWatch("獵空",R.drawable.img_8),new OverWatch("獵空",R.drawable.img_9), 9 new OverWatch("獵空",R.drawable.img_10),new OverWatch("獵空",R.drawable.img_11)}; 10 11 private List<OverWatch> overWatchList = new ArrayList<>(); 12 13 private OverWatchAdapter overWatchAdapter; 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 ... 19 20 //圖片加載 21 initOverWatch(); 22 RecyclerView reccyclerView = (RecyclerView) findViewById(R.id.recycler_view); 23 GridLayoutManager layoutManager = new GridLayoutManager(MainActivity.this,2); 24 reccyclerView.setLayoutManager(layoutManager); 25 overWatchAdapter = new OverWatchAdapter(overWatchList); 26 reccyclerView.setAdapter(overWatchAdapter); 27 } 28 29 ... 30 } 31 32 ... 33 34 //存放圖片 35 private void initOverWatch(){ 36 overWatchList.clear(); 37 for (int i = 0; i < 50; i++){ 38 Random random = new Random(); 39 int index = random.nextInt(overWatches.length); 40 overWatchList.add(overWatches[index]); 41 } 42 } 43 }
運行程序:
二、AppBarLayout
剛剛的RecyclerView把Toolbar擋住了.從布局xml中看:
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_height="match_parent" android:layout_width="match_parent" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/fab" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/ic_done" app:elevation="8dp" /> </android.support.design.widget.CoordinatorLayout>
Toolbar、RecyclerView、FloatingActionButton都是放置在CoordinatorLayout中的,因為CoordinatorLayout就是一個加強版的FrameLayout,從上到下的布局會逐漸覆蓋,所以我們可以把Toolbar的布局代碼下移試試:
但是這樣Toolbar又把RecyclerView的一部分覆蓋住了,所以再試試在CoordinatorLayout中嵌套一個LinearLayout:
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_height="match_parent" android:layout_width="match_parent" /> </LinearLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/fab" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/ic_done" app:elevation="8dp" /> </android.support.design.widget.CoordinatorLayout>
然后就完成了:
然后其實這里想講的是AppBarLayout,其實AppBarLayout就是垂直方向上的LinearLayout不過是在其內部做了很多滾動事件的封裝,所以可以用AppBarLayout避免這個遮擋
先把Toolbar嵌套到AppBarLayout中,然后給RecyclerView指定一個布局行為:
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_height="match_parent" android:layout_width="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/fab" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/ic_done" app:elevation="8dp" /> </android.support.design.widget.CoordinatorLayout>
效果和使用LinearLayout一樣。但是AppBarLayout做了一些滾動事件的封裝。比如這樣改:
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_scrollFlags="scroll|enterAlways|snap"/> </android.support.design.widget.AppBarLayout>
app:layout_scrollFlags這個屬性的值指定為scroll就是,當RecyclerView向上滾動的時候,Toolbar會隨着滾動而隱藏,enterAlways是指向下滾動的時候,snap指根據滾動的距離,自動選擇隱藏還是顯示。
三、下拉刷新
使用的是SwipeRefreshLayout然某個控件實現下拉刷新:
<android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swip_refresh" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_height="match_parent" android:layout_width="match_parent" /> </android.support.v4.widget.SwipeRefreshLayout>
將想要實現下拉刷新的某控件嵌套在SwipeRefreshLayout就行了,這里要注意把app:layout_behavior="@string/appbar_scrolling_view_behavior"這個屬性移到SwipeRefreshLayout。
然后是JAVA代碼:
public class MainActivity extends AppCompatActivity { ... private SwipeRefreshLayout swipeRefresh; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... //下拉刷新 swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swip_refresh); swipeRefresh.setColorSchemeResources(R.color.colorPrimary); swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refreshOverWatch(); } }); } ... //刷新圖片 private void refreshOverWatch(){ new Thread(new Runnable() { @Override public void run() { try{ Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { initOverWatch(); overWatchAdapter.notifyDataSetChanged(); swipeRefresh.setRefreshing(false); } }); } }).start(); } }
具體步驟就是:
1、獲取SwipeRefreshLayout的實例。
2、設置監聽器。
3、編寫刷新的使用的方法
在這里要注意的有,setColorSchemeResources()這個方法設置的是刷新時進度條的顏色,Thread.sleep(1000)先讓線程沉睡一秒,讓,然后改變數據,接着調用overWatchAdapter.notifyDataSetChanged()方法通知數據發生了變化,swipeRefresh.setRefreshing(false)用於表示刷新事件結束,並隱藏進度條。