本篇我們通過ViewPager來實現日記記錄的左右滑動查看。
重命名NoteItemActivity類爲NotePagerActivity,我們直接在這個基礎上進行修改。
要想使用ViewPager首先我們的添加相關的依賴:
同樣,我們這裏選擇的androidx下的ViewPager。
ViewPager是一種佈局管理器,它能夠允許用戶在數據頁面之間左右翻轉。 ViewPager通常和Fragment結合使用,能夠便捷的對管理每個頁面生命週期進行管理。 ViewPager需要和準適配器一起協同工作,常見爲FragmentPagerAdapterFragmentStatePagerAdapter。
`
``handlebars
創建ViewPager佈局文件
新建佈局文件activity_note_pager.xml,添加ViewPager:
```css
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/note_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_note_pager佈局與NotePagerActivity關聯
修改NotePagerActivity使其繼承BaseActivity,在getActivityLayout中返回ViewPager的資源id。
public class NotePagerActivity extends BaseActivity {
private ViewPager viewPager;
private List<NoteItem> noteItemList = new ArrayList<>();
@Override
protected void initActivityData() {
for(int i = 0; i < 20; i++){
NoteItem item = new NoteItem();
item.setNoteTitle("標題".concat(String.valueOf(i)));
item.setNoteTitle("日記內容".concat(String.valueOf(i)));
noteItemList.add(item);
}
}
@Override
protected void initActivityListener() {
}
@Override
protected void initActivityView() {
viewPager = findViewById(R.id.note_pager);
}
@Override
protected int getActivityLayout() {
return R.layout.activity_note_pager;
}
}
在 NotePagerActivity中實現FragmentStatePagerAdapter
private class NotePagerAdapter extends FragmentStatePagerAdapter {
public NotePagerAdapter(@NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
@NonNull
@Override
public Fragment getItem(int position) {
return NoteItemFragment.newInstance(noteItemList.get(position));
}
@Override
public int getCount() {
return noteItemList.size();
}
}
NotePagerAdapter 的兩個方法簡單直接。 getCount()方法返回數組列表中包含的列表項數目。getItem(int)方法纔是神奇所在,它首先獲取數據集中指定位置的NoteItem 實例,然後利用該NoteItem 實例返回一個經過有效配置的NoteItemFragment。
在實現FragmentStatePagerAdapter的時候,我們還需要提供一個構造方法,網上不少資料會使用
public FragmentStatePagerAdapter (FragmentManager fm)
在androdx中這個方法已經不推薦大家使用,替代方法是:
FragmentStatePagerAdapter(FragmentManager, int)
其中參數爲BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,該參數的意思是指定當前的fragment處於Lifecycle.State.RESUMED狀態,其他的fragment處於Lifecycle.State STARTED狀態。
FragmentStatePagerAdapter是負責管理與ViewPager的對話並協同工作。它首先將getItem(int)方法返回的fragment添加給activity,然後才能使用fragment完成自己的工作。這也就是創建FragmentStatePagerAdapter實例時,需要FragmentManager的原因。
接下我們需要創建NotePagerAdapter的實例:
@Override
protected void initActivityView() {
viewPager = findViewById(R.id.note_pager);
FragmentManager fragmentManager = getSupportFragmentManager();
notePagerAdapter = new NotePagerAdapter(fragmentManager,FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
viewPager.setAdapter(notePagerAdapter);
}
當然了,別忘了定義notePagerAdapter 變量:
private NotePagerAdapter notePagerAdapter;
其中setAdapter方法如下;
ok,經過這麼簡單的配置我們的程序就能正確的左右滑動查看了。
運行程序,雖然基礎工作做完了,但是這裏又出來一個問題,那就是使用返回鍵返回日記記錄頁面後,不管點擊哪一個列表項,進入NotePagerActivity始終顯示的是第一個記錄。
寫到這裏突然覺得BaseActivity好像又有點不太對,邊做邊改吧。。
這裏我們在BaseActivity中新增一個抽象方法initViewOptions(),用來在組件初始化後執行一些和組件有關的數據綁定等等。如果有小夥伴真的再看我寫的東西,別見怪。。。
在NotePagerActivity中實現initViewOptions方法,在其中使用setCurrentItem方法設置ViewPaper當前顯示的fragment。
androidx.viewpager.widget.ViewPager
public void setCurrentItem(int item)
@Override
protected void initViewOptions() {
NoteItem extraItem = getIntent().getParcelableExtra(NoteItemFragment.EXTRA_NOTE);
for(int i = 0; i< noteItemList.size();i++){
if(noteItemList.get(i).getUid().toString().equals(extraItem.getUid().toString())){
viewPager.setCurrentItem(i);
break;
}
}
}
這裏我們獲取Activity的intent中傳遞的數據,根據NoteItem的uid查找對應的NoteItem索引,然後設置爲ViewPaper的顯示頁面。
看看效果:
我們選擇第六個日記記錄,結果發現還是第一頁面。那麼問題出在哪裏呢?
如果真有人是一篇篇看過來的,那麼應該很快就能找到問題了,程序中使用的數據都是獨立分開的,並沒有使用同一份數據。
回憶下前面我們講過添加Gson,但是卻沒有使用。這裏我們就重新維護下我們的數據,當然了這也是臨時的,後面還是要和數據庫打交道的。
修改NoteListFragment中initFragmentData方法如下:
protected void initFragmentData() {
SharedPreferences.Editor editor = getActivity().getSharedPreferences("notelist", Context.MODE_PRIVATE).edit();
for (int i = 0; i < 20; i++) {
NoteItem noteItem = new NoteItem();
noteItem.setNoteTitle("標題".concat(String.valueOf(i)));
noteItem.setNoteContent("內容".concat(String.valueOf(i)));
noteItem.setDateCreate(new Date());
noteItemList.add(noteItem);
}
editor.putString("notelist", new Gson().toJson(noteItemList));
editor.apply();
}
這裏我們利用Gson將list對象數組轉化爲字符串,然後保存在SharedPreferences中,其本質上是一個xml文件,讓我們看看其存儲路徑:
/data/data/包名/shared_prefs/文件名.xml
/data/data/com.qiushangge.likenotes/shared_prefs/notelist.xml
當然了,獲取SharedPreferences還有兩種方式,可能文件的名稱會有所差異。
這裏需要注意的使用editor完成數據的添加後,必須要調用 editor.apply()進行提交,從而完成數據的存儲工作。
同理,我們還需要修改NotePagerActivity中獲取日記列表的代碼:
@Override
protected void initActivityData() {
SharedPreferences preferences = getSharedPreferences("notelist", MODE_PRIVATE);
String noteString = preferences.getString("notelist", "");
noteItemList = new Gson().fromJson(noteString, new TypeToken<List<NoteItem>>() {
}.getType());
}
運行程序:
ok,到這裏就算完成了。
不過呢,還有一個問題這裏我們也提出來,那就是用戶使用返回鍵的時候,比如目前頁面如下:
按下返回鍵:
頁面盡然返回了列表頁,顯然這和我們的期望有點差異,按道理來講,我們是希望返回上一篇日記內容的。
此時我們需要重載onBackPressed方法來處理用戶返回鍵:
/**
* 重載onBackPressed,處理頁面
*/
@Override
public void onBackPressed() {
if (viewPager.getCurrentItem() == 0) {
//如果當前頁面爲起始頁面,銷燬頁面,相當於finish調用
super.onBackPressed();
} else {
// 不是起始頁面,返回上一個頁面
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
}
}
此時運行程序,一切就如我們預期的一樣工作了。