前提・実現したいこと
viewPagerをつかってEditTextを含むFragmentを操作するコードを書いていて、ボタンを押したらviewPagerに含まれるすべてのFragmentにあるEditTextからgetData()したいのですが、fragmentのインスタンスをどのように取るのかで困っています。
instantiateItemを使うという解決策はキャストの問題でfragment自分で作ったfragmentのメソッドを読み込めません。
そしてviewPagerを動的に追加するために
http://qiita.com/takaaki7/items/9f135eb9e52625eb206e
この方が作ったライブラリを使っています。
どのようにviewPagerもしくはadapterからfragmentのインスタンスを取得すればよいのでしょうか。
該当のソースコード
これが取得したいfragmentです。
public class ProductFragment extends Fragment {
private View view;
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
view = inflater.inflate(R.layout.layout_product_fragment, container, false);
return view;
}
public HashMap<String,String> getData(){
HashMap<String,String> data = new HashMap<>();
data.put("name",((EditText)(view.findViewById(R.id.name))).getText().toString());
data.put("price",((EditText)(view.findViewById(R.id.price))).getText().toString());
data.put("comment",((EditText)(view.findViewById(R.id.comment))).getText().toString());
return data;
}
public static ProductFragment newInstance(int number){
Bundle bundle =new Bundle();
bundle.putInt("number", number);
ProductFragment fragment = new ProductFragment();
fragment.setArguments(bundle);
Log.d("message", "picture");
return fragment;
}
public boolean isDataNull(){
if(TextUtils.isEmpty(this.getData().get("name"))&&TextUtils.isEmpty(this.getData().get("price"))&&TextUtils.isEmpty(this.getData().get("comment"))){
return true;
}else{
return false;
}
}
}
これがadapterのコードです。先ほどのサイトで公開されているクラスを継承しています。
public class ProductFragmentAdapter extends ArrayFragmentStatePagerAdapter<Integer>{
public ProductFragmentAdapter(FragmentManager fm,int i){
super(fm,i);
}
@Override
public Fragment getFragment(Integer number , int position) {
ProductFragment fragment = ProductFragment.newInstance(number);
return fragment;
}
@Override
public void remove(int position){
super.remove(position);
}
@Override
public CharSequence getPageTitle(int position) {
return String.valueOf(position+1) + "個目の商品登録";
}
public ProductFragment getProductFragment(ViewGroup container,int position){
Fragment fragment = (Fragment)instantiateItem(container,position);
return (ProductFragment) fragment;
}
}
adapterが継承してるメソッドです
public abstract class ArrayFragmentStatePagerAdapter<T> extends ArrayPagerAdapter<T> {
private static final String TAG = "StatePagerAdapter";
private static final boolean DEBUG = false;
private final FragmentManager mFragmentManager;
private FragmentTransaction mCurTransaction = null;
private ItemsStateHandler mItemsStateHandler;
private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<>();
private ArrayList<Fragment> mFragments = new ArrayList<>();
private Fragment mCurrentPrimaryItem = null;
@SuppressLint("CommitTransaction")
@Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return super.instantiateItem(container, position);
}
}
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
Fragment fragment = getFragment(getItem(position), position);
if (DEBUG) Log.d(TAG, "Adding item #" + position + ": f=" + fragment);
if (mSavedState.size() > position) {
Fragment.SavedState fss = mSavedState.get(position);
if (fss != null) {
fragment.setInitialSavedState(fss);
}
}
while (mFragments.size() <= position) {
mFragments.add(null);
}
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
mFragments.set(position, fragment);
mCurTransaction.add(container.getId(), fragment);
return super.instantiateItem(container, position);
}
}
これが上のスーパーメソッドです
public abstract class ArrayPagerAdapter<T> extends PagerAdapter {
@Override
public Object instantiateItem(ViewGroup container, int position) {
return items.get(position);
}
/**
* Adds the specified item at the end of the array.
*
* @param item The item to add at the end of the array.
*/
public void add(T item) {
synchronized (lock) {
items.add(identifiedItemFactory.create(item));
}
itemPositionChangeChecked = new SparseBooleanArray(this.items.size());
notifyDataSetChanged();
}
/**
* Adds the specified items at the end of the array.
*
* @param items The items to add at the end of the array.
*/
}
うえで使われているクラスです
static class IdentifiedItemFactory<T> {
private long lastId;
IdentifiedItemFactory(long firstId) {
lastId = firstId;
}
IdentifiedItem<T> create(T item) {
return new IdentifiedItem(lastId++, item);
}
ArrayList<IdentifiedItem<T>> createList(List<T> items) {
ArrayList<IdentifiedItem<T>> list = new ArrayList();
for (T item : items) {
list.add(create(item));
}
return list;
}
@SafeVarargs
final ArrayList createList(T... items) {
return createList(new ArrayList<>(Arrays.asList(items)));
}
}
static class IdentifiedItem<T> {
long id;
T item;
public IdentifiedItem(long id, T item) {
this.id = id;
this.item = item;
}
@Override
public String toString() {
return "IdentifiedItem{" +
"id=" + id +
", item=" + item +
'}';
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
ProductFragmentAdapter#getProductFragmentを使うとProductFragmentでインスタンスが取得できそうですが、できない理由がありますか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/05/22 17:25
2016/05/22 18:13
1-ProductFragmentAdapterにフィールド変数、HashMap<Inreger,ProductFragment>を宣言する。
2-ProductFragmentAdapter#getFragmentでProductFragmentをreturnする前に1で宣言したHashMapに追加する。
3-全てのFrgmentにアクセスするときは1のHashMapにアクセスする。
また、ライブラリ側で何か方法が用意されているかもしれないので、ライブラリ作成者に聞いてみた方が早いかもしれないです。
2016/05/22 18:25
それも試したのですが...どうやらこのgetFragmentは単にaddした時だけに呼び出されるものではないので何回か追加と削除をしていると実際の中身とずれてきてしまうようなのです...
とりあえず現在のフラグメントのインスタンスを手に入れる変数はあったので、viewPagerの中のフラグメントが遷移したタイミングでedittextの中身をゲットしてModelとしておいたクラスに入れたり更新することで一応出来たのですが...このadapterなどをおいてるfragment側でaddされたら追加して、削除されたらModelも削除してっていちいち記述するのでとても良い解決法とは思えません...
2016/05/22 18:38
あと、「adapterが継承しているメソッドです」の意味がわからないです。
このコードはどこから来たんですか?
あなたが書いたコードはどれで、ライブラリのコードがどれか教えてください。
2016/05/22 22:35
ProductFragmentAdapterというのが僕が書いたコードで、これはArrayFragmentStatePagerAdapter<T>というクラスを継承しています。そしてこのArrayFragmentStatePagerAdapter<T>というのはArrayPagerAdapter<T>を継承していましてArrayPagerAdapter<T>がPagerAdapterを継承している形です...
ライブラリはArrayFragmentStatePagerAdapter<T>とArrayPagerAdapter<T>の部分です。PagerAdapterは元からあるクラスです。
2016/05/22 23:15
1-ProductFragmentAdapterにフィールド変数、HashMap<Inreger,ProductFragment>を宣言する。
2-ProductFragmentAdapter#getFragmentでProductFragmentをreturnする前に1で宣言したHashMapに追加する。
3-全てのFrgmentにアクセスするときは1のHashMapにアクセスする。
上記をやって不整合が発生するらしいですが、removeで削除する処理は追加しましたか?
また、ArrayFragmentStatePagerAdapterのmFragmentsにアクセスするメソッドを追加するといいと思いますが。
2016/05/22 23:58
また同じことが原因でmFragmentsにはnullが入ることがあるので取得してもしょうがないみたいです...
もともとPagerAdapterには全フラグメントのインスタンスを手に入れるというメソッドはないんですかね...やっぱり切替時にデータを取得する方法が前提なんでしょうか...
2016/05/23 10:12
あとは、mFragmentsを取得するメソッドを追加してしまうかのどちらかでしょうね。
2016/05/23 13:18