Android 記事本4

本篇我們通過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);
        }
    }

此時運行程序,一切就如我們預期的一樣工作了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章