Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ViewPager2について調べてみた
Search
Kazuki Nishida
March 14, 2019
Programming
1.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ViewPager2について調べてみた
Kazuki Nishida
March 14, 2019
Other Decks in Programming
See All in Programming
改善しないと、タスクが回らない。 “てんこ盛りポジション” を引き継いだ情シスの、入社3ヶ月の業務改善録
krm963
0
260
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
160
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
190
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
610
ここ半年くらいでAIに作らせたR用ツール
eitsupi
0
370
AI時代のPHPer生存戦略 ~「言語、もうなんでもよくない?」に本気で向き合う~
vivion
0
300
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
310
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
450
freee が目指す データ マネジメント戦略 AI-Ready 時代を支える 攻めのガバナンスとは
freee
PRO
0
300
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
670
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
4k
これって Effect でできたのでは? / TSKaigi Mashup Kansai #2
susisu
0
150
Featured
See All Featured
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
630
Context Engineering - Making Every Token Count
addyosmani
9
1k
Making Projects Easy
brettharned
120
6.7k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
480
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
450
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
How to train your dragon (web standard)
notwaldorf
97
6.7k
It's Worth the Effort
3n
188
29k
Darren the Foodie - Storyboard
khoart
PRO
3
3.6k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
56k
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
340
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が良いのではないかな。いまのところ。