如何在 android 中實現與系統相仿的照片瀏覽功能呢?這裡以 ViewPager 搭配 FragmentStatePagerAdapter 來實現系統 picture viewer 功能
ViewPager
- 是一個在 android-support-v4 才有的元件
- 其用法就像 ListView、GridView 一樣,需要一個 Adapter 來呈現畫面
- 可達到左右滑動就換頁的效果
- 通常與 Fragment 一起使用
FragmentStatePagerAdapter 與 FragmentPagerAdapter
- 都繼承至 PagerAdapter
- 每個 Item 都為 Fragment
- FragmentStatePagerAdapter:只保留當前 Fragment ( Item ),當頁面離開畫面後,就會被消毀,在頁面需要顯示時,生成新的頁面
- FragmentPagerAdapter:每個生成後的 Fragment ( Item ) 都會在内存中,適用於內容較少的靜態頁面
code解說
- view 包裝:ViewPager > FragmentStatePagerAdapter > Fragment > ProgressBar 與 ImageView
- ViewPager 的用法就像 ListView 與 GridView 一樣,這裡就不特別列出說明
- FragmentStatePagerAdapter 需實作 getCount 與 getItem method ( 這裡只列出 getItem method 說明)
@Override
public Fragment getItem(int position) {
String vo = (String) this.list.get(position);
Log.i("ruby", "Fragment getItem:" + position + " imageID:" + vo);
ImageFragment fragment = ImageFragment.newInstance(vo);
fragment.setContext(this.context); //用 setContext 將資料放入 fragment
return fragment;
}
※ 這裡值得注意的是,如何在 init 時將資料傳入 Fragment,我曾試過直接用 Bundle 傳遞,事實證明無法直接用 Bundle 傳遞,而 newInstance 這個 method,是我自訂的 method,主要用來實現將資料傳入 Fragment,method 內容稍後解釋
4. Fragment 的部分除了需要實現上面所述的 newInstance method 外,還必須複寫 onCreate、onCreateView 與 onActivityCreated method ( method 執行順序 newInstance -> onCreate -> onCreateView -> onActivityCreated )
public static ImageFragment newInstance(String path) {
ImageFragment imageFragment = new ImageFragment();
Bundle args = new Bundle();
args.putString("path", path);
imageFragment.setArguments(args); //將 args 參數綁在 Fragment 物件上
return imageFragment;
}
//初始化(onCreate → onCreateView → onActivityCreated)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
path = getArguments() != null ? getArguments().getString("path") : "";
Log.i("ruby", "ImageFragment path:"+path);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i("ruby", "onCreateView");
//先取得View才能載入元件
view = inflater.inflate(R.layout.fragment_image, container, false);
//載入物件
initComponent();
//初始化
initServerData();
rl_fragmentImage_bg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.i("ruby", "background click");
}
});
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.i("ruby", "onActivityCreated");
super.onActivityCreated(savedInstanceState);
loadBitmap();
}
※ 這部分要注意 setArguments 這個 method,他會將參數綁在 Fragment 物件上,然後可以用 getArguments method 承接
PS. Fragment 生命週期:onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume
5. 載入圖片的部分
public void loadBitmap() {
bitmap = BitmapFactory.decodeResource(getResources(), Integer.parseInt(path)); //從Resource取image
//開另外的thread載入圖片
BitmapWorkerTask task = new BitmapWorkerTask(this.context, imgv_fragmentImage_imageView, pg_fragmentImage_progressBar, bitmap.getWidth(), bitmap.getHeight());
task.execute(Integer.valueOf(path));
//設定圖片的縮放功能
new ImageViewHelper(context.getResources().getDisplayMetrics(), imgv_fragmentImage_imageView , bitmap);
}
※ 這裡要要注意的是 BitmapWorkerTask,之前直接在 main thread 加載圖片發現不管怎麼試都試不出來,後來才想到應該開另一個 thread 來載入圖片,而這裡使用 AsyncTask 來加載圖片
另外,ImageViewHelper 是做圖片縮放的部分,詳細介紹可參考 "Android 寫一個 ImageViewHelper 來處理圖片放大縮小等功能 (matrix)" 這篇文章,這裡就不再解說
由於代碼過長,這裡就不全部列出,只列出較重要與較難懂的部分,有興趣的朋友可以下載範例邊測試邊看解說,比較容易看懂!
沒有留言:
張貼留言