Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
ViewPager2について調べてみた
Kazuki Nishida
March 14, 2019
Programming
0
710
ViewPager2について調べてみた
Kazuki Nishida
March 14, 2019
Tweet
Share
Other Decks in Programming
See All in Programming
Babylon.jsで作ったsceneをレイトレーシングで映えさせる
turamy
1
210
ZOZOTOWNにおけるDatadogの活用と、それを支える全社管理者の取り組み / 2022-07-27
tippy
1
3.4k
Lookerとdbtの共存
ttccddtoki
0
660
Better Angular Architectures: Architectures with Standalone Components @DWX2022
manfredsteyer
PRO
1
450
Now in Android Overview
aosa4054
1
420
kintone × LINE Bot で餃子検定Botを作った話
naberina
0
340
アジャイルで始める データ分析基盤構築
nagano
1
920
モデルの定義に基づくバリデーションを実現するためのpydantic入門
daikikatsuragawa
0
120
How to Test Your Compose UI (Droidcon Berlin 2022)
stewemetal
1
130
Computer Vision Seminar 1/コンピュータビジョンセミナーvol.1 OpenCV活用
fixstars
0
170
2022年のモダンCSS改
tonkotsuboy_com
24
17k
10歳の minne から、これから長く続くプロダクトを作るすべての人へ
tsumichan
9
3.7k
Featured
See All Featured
The Straight Up "How To Draw Better" Workshop
denniskardys
225
130k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
498
130k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
181
15k
Done Done
chrislema
174
14k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
269
12k
Building Your Own Lightsaber
phodgson
95
4.7k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
151
13k
Web development in the modern age
philhawksworth
197
9.3k
We Have a Design System, Now What?
morganepeng
35
3k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
11
4.9k
The Power of CSS Pseudo Elements
geoffreycrofte
47
4k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
7
1.1k
Transcript
ViewPager2について調べてみた Kazuki Nishida(@kazkn_24)
みんな大好きViewPager • ViewPagerとはAndroidにおいて横方向のページャー画面を実装する為に使われる Widget • ListViewやRecyclerViewと同じようにAdapterを用いて表示要素の取得を行う • ViewPager用のAdapterとしてはFragmentPagerAdapterもしくは FragmentStatePagerAdapterを用いて1ページ=1Fragmentとして実装を行う for
Beginners
ViewPager2とは • RecyclerViewの機能を用いて作成された新しいViewPager • AdapterはRecyclerViewと同じRecyclerView.Adapterを継承したものを使用する • RTLレイアウト対応 • 縦方向のPager機能も簡単時実現可能 •
現時点(2019/03/10)では1.0.0-alpha01 https://developer.android.com/jetpack/androidx/releases/viewpager2
RecyclerViewとの関係
レシピ名 public class ViewPager2 extends ViewGroup { private RecyclerView mRecyclerView;
… private void initialize(Context context, AttributeSet attrs) { mRecyclerView = new RecyclerView(context) { … }; mRecyclerView.setId(ViewCompat.generateViewId()); mLayoutManager = new LinearLayoutManager(context); mRecyclerView.setLayoutManager(mLayoutManager); setOrientation(context, attrs); … attachViewToParent(mRecyclerView, 0, mRecyclerView.getLayoutParams()); } public final void setAdapter(@Nullable Adapter adapter) { mRecyclerView.setAdapter(adapter); } } 内部にRecyclerViewを持っている • ViewGroupを継承しており、子Viewとして RecyclerView生成する • LayoutManagerはLinerLayoutManager固定 • ViewPager2にセットしたAdapterは単純に内 部のRecyclerViewにセットされるだけ • RecyclerViewは(いまのところ)外部からは取 得する方法なし
レシピ名 public class ViewPager2 extends ViewGroup { private RecyclerView mRecyclerView;
… private void initialize(Context context, AttributeSet attrs) { … new PagerSnapHelper().attachToRecyclerView(mRecyclerView); … } } ページスナップ(1ページごとにスクロールが 止まるやつ) • PagerSnapHelperクラスで実現されているお り、PagerSnapHelper内部でRecyclerViewに 対してScrollListenerなどのコールバックを設 定している • attachToRecyclerView()のパラメータは RecyclerViewなのでViewPager2とは関係な いRecyclerViewにも適用は可能?
使い方
レシピ名 viewPager.adapter = object : RecyclerView.Adapter<ViewHolder>() { override fun onCreateViewHolder(parent:
ViewGroup, viewType: Int): ViewHolder { return ViewHolder( LayoutInflater.from(this@ViewPagerActivity1).inflate( R.layout.pager_item_text, parent, false ) ) } override fun getItemCount() = 5 override fun onBindViewHolder(holder: ViewHolder, position: Int) { val binding = DataBindingUtil.bind<PagerItemTextBinding>(holder.root) ?.apply { text = "page$position" } } } RecyclerView.Adapterを使用する例 • RecyclerView使用時と同じようなAdapterを 作ればOK • 各ページはRecyclerView.ViewHolderによっ て提供されるView
レシピ名 <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="text" type="String"/>
</data> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="@{text}" android:gravity="center"/> </layout> ページ側Layoutを作成する際の注意点 • ページ用に指定するLayoutを指定する場合、 ルートViewのサイズはwidth, heightともに match_parentを指定する • そうしないとIllegalStateExceptionで死ぬ
レシピ名 viewPager.orientation = ViewPager2.ORIENTATION_VERTICAL <androidx.viewpager2.widget.ViewPager2 … android:orientation="vertical" … /> 縦方向にスクロールする
• ページ用に指定するLayoutを指定する場合、 ルートViewのサイズはwidth, heightともに match_parentを指定する コードで指定 XMLで指定
レシピ名 viewPager.adapter = object : FragmentStateAdapter(supportFragmentManager) { override fun getItem(position:
Int) = PageFragment.newInstance("page$position") override fun getItemCount() = 5 } … class PageFragment : Fragment() { … override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = DataBindingUtil.inflate<PagerItemTextBinding>(inflater, R.layout.pager_item_text, container, false).apply { text = arguments?.getString(ARG_TEXT) }.root } } FragmentStateAdapterを使用する例 • Fragmentを使用してページを作成する場合は FragmentStateAdapterを使用する • 現時点ではOffscreenPageLimitの仕組みが 存在しないため、隣接するページのFragment の生成は実際のスクロール開始時に行われる • 生成済みのページに関してはRecyclerViewで いくつかキャッシュされるが、 RecyclerView.setItemViewCacheSize()や、 LinearLayoutManager.getExtraLayoutSpace ()のOverrideでキャッシュ数を調整したりは出 来ない
いまのところ出来ない事
いまのところ未実装 • no offscreen limit control • needs better TabLayout
integration • no pageWidth setter (forced 100%/100%) • page transformer: no hardware/software layer choice; no reverse drawing order https://developer.android.com/jetpack/androidx/releases/viewpager2 ※もうちょい色々書いてあります。 これ
Groupie使える?
レシピ名 viewPager.adapter = GroupAdapter<ViewHolder>().apply { add(TextItem("page1")) add(TextItem("page2")) add(TextItem("page3")) add(TextItem("page4")) add(TextItem("page5"))
} } private class TextItem( private val text: String ) : BindableItem<PagerItemTextBinding>() { override fun getLayout() = R.layout.pager_item_text override fun bind(viewBinding: PagerItemTextBinding, position: Int) { viewBinding.text = text } } 単純な使用例 • GroupieのGroupAdapterは RecyclerView.Adapterを継承しているので普 通に使える • 自前でAdapterを実装するよりは少し楽かもし れない。
レシピ名 viewPager.adapter = GroupAdapter<ViewHolder>().apply { add(TextItem("page1")) add(ImageItem("world_press17.jpg")) add(TextItem("page3")) add(ImageItem("181126jpower.jpg")) add(TextItem("page5"))
add(ImageItem("img_473_1488875864.jpg")) } 単純な使用例2 • 当然、異なる形のページをGroupieのItemとし て表現する事も可能 • ViewTypeが複数ある場合は自前でAdapter 作るよりもだいぶ便利かもしれない
レシピ名 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) … groupLayoutManager
= GridLayoutManager(this, groupAdapter.spanCount).apply { spanSizeLookup = groupAdapter.spanSizeLookup } ) … recyclerView.apply { layoutManager = groupLayoutManager } グリッド表示 • LayoutManagerがLinerLayoutManagerなの で実現できません!!!! Groupieのサンプルコードから これ
レシピ名 viewPager.adapter = GroupAdapter<ViewHolder>().apply { add(Section().apply { setHeader(TextItem("header")) setFooter(TextItem("footer")) add(TextItem("page1"))
add(TextItem("page2")) add(TextItem("page3")) }) } セクションヘッダー、フッター付き • 使えるけども、 Header→Item→Item→Item→Footerと表示 されるだけなので、まぁ、なんか使えるかもしれ ない…
感想 • 基本的には実績のあるRecyclerViewの実装に依存するので、alphaだけど安定性 は高いと思う • 旧ViewPagerに実装されていたpageWidthなどの設定が出来ないので、ちょっと凝っ たレイアウトの場合はまだ旧ViewPagerを使うほうがいい • Offscreen Page
Limitの仕組み、キャッシュなどの動きを考えるとページの構成物 がImageViewだけみたいな場合にはViewPager2、Fragment内に複雑なレイアウトを 必要とする場合はViewPagerが良いのではないかな。いまのところ。