5

Fragmentを表示するには、ACLのViewPagerを使用しています。最初に、これらのフラグメントはすべてListFragmentにリストが含まれています。私は2列テーブルを模倣しようとしているので、リストの各要素には2つのオブジェクトの別のリストが含まれています。私は各セルをリスト項目全体ではなく、クリック可能にしたいので、独自のColumnLayoutを実装しました(たぶんCellLayoutと呼ばれるべきです)。各リスト項目には、2つのColumnLayoutsが含まれています。これらはLongClickableで、どのエンティティが長押しされたかに関する情報を返すためにgetContextMenuInfo()を実装しています。このメソッドは、ViewPagerを検索し、現在のフラグメントを尋ねてから、そのフラグメントを呼び出して、長押しされたビューからエンティティIDを返します。正しい行を取得するには、フラグメントにする必要があります。ViewPagerのフラグメントでonCreateViewが呼び出されていません

ここで問題が発生します。 getListView()IllegalStateException「コンテンツビューがまだ作成されていません」とスローすることがあります。私。 onCreateView(...)が呼び出されていません。これは、アプリが再開されたときにのみ発生します。今日は、私のGalaxy Nexusで[設定]> [デベロッパーオプション]の[アクティビティを保存しない]オプションを有効にして問題を再現しました。私は、アプリを起動し、ホームを押して、最近のアプリメニューからアプリを再度開いて、今度はリストビュー内のセルのどれかを長押しするとこの例外がスローされます。いくつかのデバッグ出力によって、私はonCreateViewが一度も呼び出されていないことを確認することができました。 FragmentとそのListViewとそのセル項目を持つViewPager全体がすべて描画されるので、これは奇妙です。

ACL内のListFragmentがカスタムレイアウトをサポートしていないことが#android-devに伝えられたので、ListFragmentを使わずにandroid.support.v4.app.Fragmentを再実装しましたが、それは役に立たなかった。

短い要約:私は押され、細胞内entitiyについての情報を含むMenuInfoオブジェクトを作成する目的のために長押しレイアウトのイベントを処理するカスタムレイアウトを持っています。レイアウトに含まれるエンティティを見つけるには、最終的にlistview.getPositionForView(View v)が呼び出され、IllegalStateExceptionが発生することがあります。

ここに私のカスタムレイアウト(おそらく、ビュー階層に掘るよりViewPagerのホールドを取得する簡単な方法があります):

package org.remotestick; 

import android.content.Context; 
import android.support.v4.view.ViewPager; 
import android.util.AttributeSet; 
import android.view.ContextMenu.ContextMenuInfo; 
import android.view.View; 
import android.widget.LinearLayout; 

public class ColumnLayout extends LinearLayout { 

    public ColumnLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public ColumnLayout(Context context) { 
     super(context); 
    } 

    @Override 
    protected ContextMenuInfo getContextMenuInfo() { 
     int itemTypeId = getChildAt(0).getId(); 
     int positionTypeId = getId(); 
     View currentView = this; 
     ViewPager viewPager = null; 
     while(currentView.getParent() != null) { 
      currentView = (View) currentView.getParent(); 
      if(currentView.getId() == R.id.pager) { 
       viewPager = (ViewPager) currentView; 
       break; 
      } else if (currentView.getId() == R.id.rootLayout) 
       break; 
     } 
     if(viewPager == null) 
      return null; 

     WorkspaceAdapter adapter = (WorkspaceAdapter) viewPager.getAdapter(); 
     Pair<Integer, Integer> itemIdAndListPosition = adapter.getItemIdFromWorkspace(viewPager.getCurrentItem(), this, itemTypeId, (positionTypeId == R.id.leftColumn)); 
     if(itemIdAndListPosition == null) 
      return null; 
     else 
      return new MatrixAdaptableContextMenuInfo(itemTypeId, itemIdAndListPosition.first, itemIdAndListPosition.second); 
    } 

    public static class MatrixAdaptableContextMenuInfo implements ContextMenuInfo { 

     public final int itemTypeId; 
     public final Integer itemId; 
     public final Integer positionInList; 

     public MatrixAdaptableContextMenuInfo(int itemTypeId, Integer itemId, Integer positionInList) { 
      this.itemTypeId = itemTypeId; 
      this.itemId = itemId; 
      this.positionInList = positionInList; 
     } 

    } 
} 

そして、ここだFragment(の抜粋):

public class EntityTableFragment extends Fragment implements TelldusEntityChangeListener { 

    protected static final String ARG_TITLE = "title"; 

    protected MatrixAdapter mAdapter; 
    protected ProgressViewer mProgressViewer; 
    protected MatrixFilter mFilter; 
    protected Handler mHandler = new Handler(); 
    protected RemoteStickData db; 

    public boolean onAttach = false; 
    public boolean onCreateView = false; 

    private ListView listView; 

    public static EntityTableFragment newInstance(String title) { 
     EntityTableFragment f = new EntityTableFragment(); 

     Bundle args = new Bundle(); 
     args.putString(ARG_TITLE, title); 
     f.setArguments(args); 
     return f; 
    } 

    @Override 
    public void onAttach(SupportActivity activity) { 
     super.onAttach(activity); 
     onAttach = true; 
      try { 
      mProgressViewer = (ProgressViewer) activity; 
      mAdapter = new MatrixAdapter(getActivity(), mProgressViewer, new ArrayList<List<MatrixEntity>>(), null); 
      TelldusLiveService.addListener(this); 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() + " must implement ProgressViewer"); 
     } 
     db = new RemoteStickData(getActivity()); 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     TelldusLiveService.removeListener(this); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     listView.setAdapter(mAdapter); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.list, null); 
     listView = (ListView) view.findViewById(R.id.list); 
     return view; 
    } 

    @Override 
    public String toString() { 
     return getArguments().getString(ARG_TITLE); 
    } 

    public Pair<Integer, Integer> getIdAndPositionForView(View v, boolean isLeft) { 
     if(listView == null) 
      throw new IllegalStateException("Listview not yet created"); 
     int positionForView = listView.getPositionForView(v); 
     if(isLeft) 
      return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(0).getId(), positionForView); 
     else 
      return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(1).getId(), positionForView); 
    } 

アプリを再開すると(アクティビティが破棄された場合)、そのフラグメントとそのListViewとカスタムレイアウトを持つViewPagerがすべて描画されるのはむしろ奇妙なことではありませんか?しかし、私はIllegalStateExceptionを得て、リストビュー内のセルのどれかを長押しするとビューが作成されていないと言っていますか?/

編集は実は、onCreateViewLog.d(Constants.TAG, "onCreateView!!!!");出力は、メソッドが、私はアプリ(ViewPagerの各フラグメントに1つ)を起動しますが、アプリケーションが再開されたとき、それが再び呼び出されることはありませんだ2回の最初の時間に呼び出されることを示しています! ?それはバグですか、何が間違っているのでしょうか?

答えて

4

重要な部分はFragmentPagerAdapter(私は含まれていませんでした)のようです。デバッグでは、アクティビティが再作成されたときにgetItem()が呼び出されないことが示されています。フラグメントは他の方法で再作成されます。つまり、FragmentPagerAdapterの実装では、FragmentManagerのフラグメントへの間違った参照がありました。

その代わりに、フラグメントを検索する必要があるときは、適切なタグ名を取得するためにmakeFragmentName()を使用してfindFragmentByTag()FragmentManagerにある)を使用します。これは、フラグメントが追加されるときにFragmentPagerAdapterによって使用される方法です。これが安全なアプローチかどうかは分かりません。

関連する問題