[解決済み】ViewPagerを動的に更新しますか?
質問
ViewPagerのコンテンツが更新できないのですが。
FragmentPagerAdapterクラスのメソッドinstantiateItem()とgetItem()の正しい使い方を教えてください。
フラグメントをインスタンス化して返すのに、getItem()だけを使っていました。
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
これはうまくいきました。コンテンツを変更できないことを除けば。
そこで、こんなものを見つけました。 ViewPager PagerAdapterがビューを更新しない
"私のアプローチは、instantiateItem()メソッドでインスタンス化されたすべてのビューに対してsetTag()メソッドを使用することです"
さて、そのためにinstantiateItem()を実装したいのですが。しかし、私は何を返さなければならないのか(型はObject)、getItem(int position)との関係はどうなっているのかがわかりません。
を読みました。 参照 :
public abstract Fragment getItem (int position)
指定された位置に関連するFragmentを返します。
public Object instantiateItem (ViewGroup container, int position)
指定された位置のページを作成します。アダプタは、ここで指定されたコンテナにビューを追加する責任を負いますが、 finishUpdate(ViewGroup) から戻るまでに、これが完了していることを確認する必要があります。 パラメータ
container ページが表示される View を含みます。 position インスタンス化されるページ位置。
戻り値
新しいページを表すオブジェクトを返します。これは View である必要はなく、ページの他のコンテナであっても構いません。
が、やはり理解できない。
以下は私のコードです。私はサポートパッケージv4を使っています。
ViewPagerTest
public class ViewPagerTest extends FragmentActivity {
private ViewPager pager;
private MyFragmentAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager1);
pager = (ViewPager)findViewById(R.id.slider);
String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};
adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
pager.setAdapter(adapter);
((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
reload();
}
});
}
private void reload() {
String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
//adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
adapter.setData(data);
adapter.notifyDataSetChanged();
pager.invalidate();
//pager.setCurrentItem(0);
}
}
MyFragmentAdapter
class MyFragmentAdapter extends FragmentPagerAdapter {
private int slideCount;
private Context context;
private String[] data;
public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.data = data;
}
@Override
public Fragment getItem(int position) {
return new MyFragment(data[position], context);
}
@Override
public int getCount() {
return slideCount;
}
public void setData(String[] data) {
this.data = data;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
MyFragment
public final class MyFragment extends Fragment {
private String text;
public MyFragment(String text, Context context) {
this.text = text;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slide, null);
((TextView)view.findViewById(R.id.text)).setText(text);
return view;
}
}
ここにも同じような問題を抱えた人がいますが、回答はありません。 http://www.mail-archive.com/[email protected]/msg200477.html
解決方法は?
FragmentPagerAdapter や FragmentStatePagerAdapter を使用する場合、以下のように、FragmentStatePagerAdapter のみを扱うのがベストです。
getItem()
に触れず
instantiateItem()
を全く使用しない。その
instantiateItem()
-
destroyItem()
-
isViewFromObject()
インターフェースは、FragmentPagerAdapter が、より単純な
getItem()
インターフェイスを使用します。
この話に入る前に、以下のことを明らかにしておきます。
実際に表示されているフラグメントを切り替えたい場合は、FragmentPagerAdapter を避けて、FragmentPagerAdapter を使用する必要があります。 FragmentStatePagerAdapterです。
この回答の以前のバージョンでは、例としてFragmentPagerAdapterを使うというミスがありました。FragmentPagerAdapterは、最初に表示された後は決してフラグメントを破棄しないので、これはうまくいきません。
を使うのはお勧めしません。
setTag()
と
findViewWithTag()
は、リンク先の投稿で提供されている回避策です。あなたが発見したように
setTag()
と
findViewWithTag()
はフラグメントでは動作しないので、相性が悪いです。
を上書きするのが正しい解決策です。
getItemPosition()
. いつ
notifyDataSetChanged()
が呼び出されると、ViewPager は
getItemPosition()
を使用して、 アダプタ内のすべてのアイテムを別の場所に移動したり削除したりする必要があるかどうかを調べます。
デフォルトでは
getItemPosition()
は
POSITION_UNCHANGED
これは、「このオブジェクトは今のままでよいので、壊したり取り除いたりしないでください」という意味です。
POSITION_NONE
はこの問題を解決するために、代わりに "このオブジェクトはもう表示するアイテムではないので、削除してください。
これは完全に正当な修正です! この修正により、notifyDataSetChanged はビューリサイクルを行わない通常のアダプタのように動作するようになります。この修正を実装し、パフォーマンスが満足のいくものであったなら、本番に突入です。これで完了です。
より良いパフォーマンスが必要な場合は、よりファンシーな
getItemPosition()
を実装しています。以下は、文字列のリストからフラグメントを作成するページャの例です。
ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();
FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
public int getCount() {
return titles.size();
}
public Fragment getItem(int position) {
MyFragment fragment = new MyFragment();
fragment.setTitle(titles.get(position));
return fragment;
}
public int getItemPosition(Object item) {
MyFragment fragment = (MyFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
});
この実装では、新しいタイトルを表示するフラグメントのみが表示されます。まだリストに残っているタイトルを表示しているフラグメントは、リスト内の新しい位置に移動され、リストに残っていないタイトルを表示しているフラグメントは破棄されます。
フラグメントが再作成されていないが、とにかく更新する必要がある場合はどうすればよいですか?生きているフラグメントの更新は、そのフラグメント自身が行うのが最善です。これがフラグメントを持つ利点です。つまり、フラグメント自身がコントローラなのです。フラグメントは、リスナーまたはオブザーバーを
onCreate()
で削除し
onDestroy()
このように、更新を自ら管理することができます。すべての更新コードを
getItem()
ListView や他の AdapterView タイプのアダプタのように。
最後に、FragmentPagerAdapter がフラグメントを破棄しないからといって、getItemPosition が FragmentPagerAdapter の中で全く役に立たないというわけではありません。このコールバックを使用して、ViewPager 内のフラグメントの順序を変更することができます。しかし、フラグメントを FragmentManager から完全に削除することはできません。
関連
-
[解決済み】インストールエラー。インストールエラー:install_failed_older_sdk
-
[解決済み】シンボル 'AppCompatActivity' を解決できない。
-
[解決済み】Android Studioです。「プロジェクトが C ドライブに作成されている場合、「タスク ':app:mergeDebugResources' の実行に失敗しました。
-
[解決済み】Build Tools リビジョン 23.0.1 の検索に失敗しました。
-
[解決済み】IllegalStateException: ViewPager で onSaveInstanceState の後にこのアクションを実行できません。
-
[解決済み] エラー - Android リソースのリンクに失敗しました (AAPT2 27.0.3 Daemon #0)
-
[解決済み] ViewPagerでFragmentが表示されるタイミングを決定する方法
-
[解決済み] ViewPager PagerAdapter がビューを更新しない
-
[解決済み] ViewPagerとフラグメント - フラグメントの状態を保存する正しい方法は何ですか?
-
[解決済み] ViewPagerの一部であるListFragmentのデータを更新する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Dalvikとdalvik-cacheとは何ですか?
-
[解決済み] [Solved] Unsupported method: ベースコンフィグ.getApplicationIdSuffix()
-
[解決済み】リストビューにonclicklistenerを追加する(android)
-
[解決済み】apkファイルのインストール中に「パッケージが破損しているようです」というエラーが発生する。
-
[解決済み】getCheckedRadioButtonId()が無駄なintを返す?
-
[解決済み] サポートされていないメソッドです。BaseConfig.getApplicationIdSuffix()がサポートされていません。
-
[解決済み] Android Studioで「URIが登録されていません」と報告されるのはなぜですか?[クローズド]
-
[解決済み] com.android.supportのライブラリは全て全く同じバージョン表記である必要があります。
-
[解決済み] ViewPager PagerAdapter がビューを更新しない
-
[解決済み] ビューページャーへのビューの動的な追加と削除