繼續使用上篇文章的項目,拷貝一份並改名爲
day21_SwipeRefresh
一、下拉刷新
SwipeRefresh
是用於刷新功能的核心類,將想要實現刷新功能的控件放置到SwipeRefreshLayout
中即可
比如我們要刷新RecycleclerView
:
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
需要注意,因爲RecyclerView
現在是SwipeRefresh
的子控件,所以app:layout_behavior
也要移到SwipeRefreshLayout
中
差點忘了添加依賴:
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' // 下拉刷新
接着修改主活動,添加刷新邏輯:
private SwipeRefreshLayout swipeRefreshLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
......
swipeRefreshLayout = findViewById(R.id.swipe_refresh);
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
refreshFruits();
}
});
}
private void refreshFruits() {
new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
initFruits();
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
});
}
}).start();
}
setColorSchemeResources()
設置進度條顏色
setOnRefreshListener()
設置下拉刷新監聽器,回調onRefresh()
serRefreshing(false)
表示刷新事件結束,並隱藏刷新進度條
運行:
二、可摺疊標題欄
Toolbar
和傳統標題欄看起來沒啥兩樣,不過可以響應RecyclerView
的滾動事件進行隱藏和顯示。爲了實現一個可摺疊的標題欄,需要藉助CollapsingToolBarLayout
CollapsingToolBarLayout
這個佈局作用於Toolbar
,可以讓其效果更豐富,但它被限定只能作爲AppBarLayout
子佈局使用,而AppBarLayout
又必須是CoordinatorLayout
的子佈局。
新建一個額外的FruitActivity
來展示水果詳情頁面,其對應佈局:
a. 佈局
activity_fruit.xml
的三層套路:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
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="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="@+id/appBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/collapsing_toolbar"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
app:contentScrim
:用於指定CollapsingToolbarLayout
在趨於摺疊狀態及摺疊狀態之後的背景色
app:layout_scrollFlags
:之前給ToolBar
指定的,現在移到外面:
scroll
表示CollapsingToolbarLayout
會隨着水果詳情的滾動一起滾動exitUntilCollapsed
表示當CollapsingToolbarLayout
隨着滾動完成或摺疊之後就保留在界面上,不再移除屏幕
繼續在CollapsingToolbarLayout
中定義標題欄的具體內容:
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fruit_image_view"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"/>
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/toolbar"
app:layout_collapseMode="pin"/>
app:collapseMode
用於指定當前控件在CollapsingToolbarLayout
摺疊過程中的摺疊方式:
pin
:位置不變parallax
:摺疊會產生一定的錯位偏移
接着在和<AppBarLayout>
平級的下面編寫內容部分:
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
NestedScrollView
允許用滾動的方式查看屏幕之外的數據,還增加了嵌套響應事件的功能
接着在NestedScrollView
內添加布局:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="35dp"
app:cardCornerRadius="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:id="@+id/fruit_content"/>
</androidx.cardview.widget.CardView>
</LinearLayout>
最後給NestedScrollView
同級之下添加懸浮按鈕:
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/like"
app:layout_anchor="@id/appBar"
app:layout_anchorGravity="bottom|end"/>
app:layout_anchor
指定錨點,將錨點設置爲AppBarLayout
,這樣懸浮按鈕就會出現在水果標題欄的區域內
app:layout_anchorGravity
:出現在標題欄的右下角
b. 活動
FruitActivity
public class FruitActivity extends AppCompatActivity {
public static final String FRUIT_NAME = "fruit_name";
public static final String FRUIT_IMAGE_ID = "fruit_image_id";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fruit);
Intent intent = getIntent();
String fruitName = intent.getStringExtra(FRUIT_NAME);
int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID, 0);
Toolbar toolbar = findViewById(R.id.toolbar);
CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
ImageView fruitImageView = findViewById(R.id.fruit_image_view);
TextView fruitContentText = findViewById(R.id.fruit_content);
setSupportActionBar(toolbar);
ActionBar actionBar =getSupportActionBar();
if (actionBar != null){
actionBar.setDisplayHomeAsUpEnabled(true);
}
collapsingToolbarLayout.setTitle(fruitName);
Glide.with(this).load(fruitImageId).into(fruitImageView);
String fruitContent = generateFtuitContent(fruitName);
fruitContentText.setText(fruitContent);
}
private String generateFtuitContent(String fruitName) {
StringBuilder fruitContent = new StringBuilder();
for (int i = 0; i<500; i++){
fruitContent.append(fruitName);
}
return fruitContent.toString();
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
actionBar.setDisplayHomeAsUpEnabled(true);
顯示標題欄的按鈕【默認是返回按鈕】
CollapsingToolbarLayout.setTitle()
設置標題
onOptionsItemSelected()
設置了返回按鈕的點擊事件
c. 適配器
FruitAdapter
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (mContext == null){
mContext = parent.getContext();
}
View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Intent intent = new Intent(mContext, FruitActivity.class);
intent.putExtra(FruitActivity.FRUIT_NAME, fruit.getName());
intent.putExtra(FruitActivity.FRUIT_IMAGE_ID, fruit.getImageId());
mContext.startActivity(intent);
}
});
return holder;
}
也就是給CardView
註冊了一個監聽器~
4. 展示
三、融合狀態欄
狀態欄融合是Android5.0以後才支持的的樣式
1、一個屬性
要想使背景圖和系統狀態欄融合,需藉助android:fitsSystemWindows
這個屬性來實現,將本例中的ImageView
及其所有父佈局全部設置這個屬性:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
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="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="@+id/appBar"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/collapsing_toolbar"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
android:fitsSystemWindows="true">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fruit_image_view"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
android:fitsSystemWindows="true"/>
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/toolbar"
app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="35dp"
app:cardCornerRadius="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:id="@+id/fruit_content"/>
</androidx.cardview.widget.CardView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/like"
app:layout_anchor="@id/appBar"
app:layout_anchorGravity="bottom|end"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
2、設置透明
在主題中,將android:statusBarColor
指定成@android:color/transparent
,但只有Android5.0 之後纔可以這麼設置,所以這裏就要實現系統差異處理了。
在res
下新建一個values-v21
目錄,在裏面建一個values_resource
文件styles.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="FruitActivityTheme" parent="AppTheme">
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
這裏定義了一個FruitActivityTheme
主題,它是專門給FruitActivity
使用的,其parent
主題是Apptheme
,就是說他繼承了AppTheme
的所有特性,然後將其狀態欄的顏色指定爲透明色,而values-v21
是隻有Android5.0以上的系統纔會讀取,因此這麼聲明沒問題
接着爲5.0之前的系統單獨單的設置values/style.xml
文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="FruitActivityTheme" parent="AppTheme" />
</resources>
這裏也定義了一個FruitActivityTheme
主題,並且parent
主題也是AppTheme
,但內部是空的,因爲5.0之前無法指定狀態欄顏色,所以這裏啥都不用做
接着在AndroidManifest.xml
中讓FruitActivity
使用這個主題:
<activity android:name=".FruitActivity"
android:theme="@style/FruitActivityTheme">
</activity>