ViewPager的使用

tiger.wang 9年前發布 | 12K 次閱讀 ViewPager Android開發 移動開發

來自: https://segmentfault.com/a/1190000004544713

一 前言

上次我們用RecyclerView做了一個簡單的顯示筆記的小程序,今天我們用ViewPager來擴展它的功能:當我們點擊筆記列表的其中某條筆記時,它可以跳到另外一個頁面完整的顯示這條筆記的內容,更人性化的設計是,在某條筆記的詳情頁面,我們可以左右滑動以查看上一條或者下一條,而不是返回主列表再去選擇,話不多說,操作起來!

二 準備工作

1.首先我們創建一個Activity,命名為NotePagerActivity2.定義NotePagerActivity的私有字段:

public class NotePagerActivity extends AppCompatActivity {
    private static final String EXTRA_NOTE_ID = "com.aristark.note.note.id";
    private ViewPager noteViewPager;
    private ArrayList<Note> notes;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_note_pager);
}

}</pre>

因為我們是從列表Activity那里點擊某一個筆記項才進入到NotePagerActivity,因此需要傳入該筆記項的UUID(很容易想到兩個Activity之間傳遞數據所使用的方法是Intent附加參數,也就是putExtra()方法,因此我們將該常量命名為EXTRA_NOTE_ID,養成這樣良好的命名方法對以后讀懂這段代碼是很重要的!先不用好奇為什么要把它設為私有,一會兒就明白其中的妙處了),noteViewPager和notes自然不用多說,這是今天的主角。

3.在布局中activity_note_pager設置ViewPager直接上代碼

<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/activity_note_pager_view_pager"/>
    

4為NotePagerActivity編寫newIntent方法

public static Intent newIntent(Context context,UUID uuid){
    Intent i = new Intent(context,NotePagerActivity.class);
    i.putExtra(EXTRA_NOTE_ID,uuid);
    return i;
}

這樣我們每次想要啟動NotePagerActivity時只需調用這個靜態方法,而不用再balabalabala重復一堆昨天的故事。

三 設置ViewPager

其實我也不知道為什么用設置這個詞,應該用使用?裝配?其實不需要太在意,我們的目的現在很簡單,就是按照ViewPager給的接口傳入相應的參數,讓它工作起來就行(對新手而言)!先貼上NoteListsFragment的代碼

package com.aristark.note;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList; import java.util.Calendar; import java.util.List;

public class NotesListFragment extends Fragment { private RecyclerView noteRecycler; private NoteAdapter noteAdapter;</pre>

    public NotesListFragment() {
        // Required empty public constructor
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        // Inflate the layout for this fragment
//        return inflater.inflate(R.layout.fragment_notes_list, container, false);
        View root = inflater.inflate(R.layout.fragment_notes_list,container,false);

    noteRecycler = (RecyclerView) root.findViewById(R.id.note_recycler_view);
    noteRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));

// NoteLab noteLab = NoteLab.getNoteLab(getActivity()); // ArrayList<Note> notes = noteLab.getNotes(); // noteAdapter = new NoteAdapter(notes); // noteRecycler.setAdapter(noteAdapter); updateView(); return root; }

@Override
public void onResume() {
    super.onResume();
    updateView();
}

private class NoteHolder extends RecyclerView.ViewHolder{
    private TextView noteTitle;
    private TextView noteContent;
    private TextView noteDate;

    public NoteHolder(View root) {
        super(root);
        noteTitle = (TextView) root.findViewById(R.id.list_item_note_title);
        noteContent = (TextView) root.findViewById(R.id.list_item_note_content);
        noteDate = (TextView) root.findViewById(R.id.list_item_note_date);
    }

    public void bindView(Note n){
        this.note = n;
        noteTitle.setText(note.getTitle());
        noteContent.setText(note.getContent());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(note.getDate());
        int year = calendar.get(1);
        int day = calendar.get(5);
        int month = calendar.get(2)+1;
        String date = year+"年"+month+"月"+day+"日";
        noteDate.setText(date);
    }

}

private class NoteAdapter extends RecyclerView.Adapter<NoteHolder>{
    private List<Note> notes;

    public NoteAdapter(List<Note> notes){
        this.notes = notes;
    }

    public void setNotes(List<Note> notes) {
        this.notes = notes;
    }

    @Override
    public NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
        View view = layoutInflater.inflate(R.layout.list_item_note,parent,false);
        return new NoteHolder(view);
    }

    @Override
    public void onBindViewHolder(NoteHolder holder, int position) {
        Note note = notes.get(position);
        holder.bindView(note);
    }

    @Override
    public int getItemCount() {
        return notes.size();
    }
}

public void updateView(){
    NoteLab noteLab = NoteLab.getNoteLab(getActivity());
    ArrayList<Note> notes = noteLab.getNotes();
    if (noteAdapter == null){
        noteAdapter = new NoteAdapter(notes);
        noteRecycler.setAdapter(noteAdapter);
        return;
    }

    noteAdapter.setNotes(notes);
    noteRecycler.setAdapter(noteAdapter);

}

}</pre>

和上回的代碼略有不同,我做了一些小小的封裝。我們把注意力集中到類NoteHolder的構造方法這里來,它傳入的參數root的類型是View,也就是筆記列表項的每一個筆記記錄,我們在這里設置一個監聽器,當用戶點擊的時候,我們就讓頁面跳轉到筆記詳情頁面,也就是CrimePagerActivity,來,寫代碼:

    public NoteHolder(View root) {
        super(root);
        root.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = NotePagerActivity.newIntent(getActivity(),note.getUuid());
                startActivity(i);
            }
        });
        noteTitle = (TextView) root.findViewById(R.id.list_item_note_title);
        noteContent = (TextView) root.findViewById(R.id.list_item_note_content);
        noteDate = (TextView) root.findViewById(R.id.list_item_note_date);
    }

下面把注意力轉移到CrimePagerActivity:1.獲取ViewPager:

 noteViewPager = (ViewPager) findViewById(R.id.note_view_pager);

2.從傳來的Intent里獲取uuid,并以此uuid從全局靜態對象NoteLab中獲取notes:

 UUID uuid = (UUID)getIntent().getSerializableExtra(EXTRA_NOTE_ID);
 notes = NoteLab.getNoteLab(this).getNotes();

這里再一次體會到了EXTRA_NOTE_ID的方便之處吧。3.為ViewPager設置Adapter(ViewPager和RecyclerView一樣,每個頁面的布局都是一樣的,只是填充的數據不一樣,因為需要Adapter去適配,這里感嘆一句想到這種機制的大神真的應該膜拜!簡直解放了生產力有沒有!)OK,show you the code:

 FragmentManager fragmentManager = getSupportFragmentManager();
        noteViewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
            @Override
            public Fragment getItem(int position) {
                return null;
            }

        @Override
        public int getCount() {
            return notes.size();
        }
    });</pre> 

是不是似曾相識?之所以要用FragmentPagerAdapter,是因為它可以為我們省去從Activity中啟動Fragment的一系列事務代碼,十分方便。寫到這里我忽然忘記我們把筆記詳情頁給忘了,沒有它我們該拿什么去顯示筆記的詳情呢,好吧,趕快去新建一個fragment命名為NoteDetailFragment:

public class NoteDetailFragment extends Fragment {
    private static String ARG_NOTE_ID;
    private Note note;
    TextView noteDate;
    TextView noteTitle;
    TextView noteContent;

public NoteDetailFragment() {
    // Required empty public constructor
}

 public static Fragment newFragment(UUID uuid){
     Bundle args = new Bundle();
     args.putSerializable(ARG_NOTE_ID,uuid);
     Fragment fragment = new NoteDetailFragment();
     fragment.setArguments(args);
     return fragment;

 }

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    UUID uuid = (UUID) getArguments().getSerializable(ARG_NOTE_ID);
    note = NoteLab.getNoteLab(getActivity()).getNote(uuid);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_note_detail,container,false);
    noteDate = (TextView) root.findViewById(R.id.note_date);
    noteTitle = (TextView) root.findViewById(R.id.note_title);
    noteContent = (TextView) root.findViewById(R.id.note_content);
    noteDate.setText(note.getDate().toString());
    noteTitle.setText(note.getTitle());
    noteContent.setText(note.getContent());
}
return root;

}</pre>

上面的newFragment方法和之前的newIntent所使用的技巧是一樣的。從Activity中啟動Fragment傳參的方法是setArguments,自然的,我們就有了ARG_NOTE_ID這個常量。對應的布局文件代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/note_date"
    android:layout_weight="3"/>

<View android:layout_height="1px" android:background="@android:color/darker_gray" android:layout_width="fill_parent"></View></pre> 

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/note_title"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/note_content" />

    </LinearLayout>

</LinearLayout>

</LinearLayout></pre>

回到NotePagerActivity中:

  @Override
        public Fragment getItem(int position) {
            Note note = notes.get(position);
            return NoteDetailFragment.newFragment(note.getUuid());
        }

好,編譯,運行,添加幾組測試數據后我們會發現不管從哪條筆記記錄點擊進去,都是從第一條開始顯示,不用急,此時我們可以在getItem下面添加如下代碼:

for (int i=0;i<notes.size();i++){
            if (notes.get(i).getUuid().equals(uuid)){
                noteViewPager.setCurrentItem(i);
                break;
            }
        }

用setCurrentItem來設置正確的筆記項就行了。因為結果需要動態演示,我就不貼圖啦,如果有人需要代碼的話我就聯系我吧!我的qq:891871898求批評指正!

</div>

 本文由用戶 tiger.wang 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!