5

ACL에서 ViewPager을 사용하여 Fragment을 표시합니다. 처음에는이 단편 모두가 목록이 들어있는 ListFragment입니다. 목록의 각 요소에 두 개의 개체 목록이 포함되어 있으므로 2 열 표를 모방하려고합니다. 각 셀을 전체 목록 항목이 아닌 클릭 할 수 있도록하려면 자체 ColumnLayout을 구현했습니다 (아마도 CellLayout이라고해야합니다). 각 목록 항목에는 클릭 할 수있는 두 개의 ColumnLayouts가 있으며 어떤 항목을 길게 클릭했는지에 대한 정보를 반환하기 위해 getContextMenuInfo()을 구현합니다. 이 메소드는 ViewPager를 검색하고 현재 조각을 요청한 다음 프래그먼트를 호출하여 길게 클릭 된보기에서 엔티티 ID를 리턴합니다. 조각을 처리하려면 올바른 행을 얻기 위해 다음을 수행해야합니다.onCreateView가 ViewPager에서 Fragment와 함께 호출되지 않았습니다.

여기가 문제의 시작입니다. getListView()IllegalStateException "콘텐츠 뷰가 아직 생성되지 않았습니다."라고 말하는 경우가 있습니다. 나는. onCreateView(...)이 (가) 호출되지 않았습니다. 이는 앱이 다시 시작될 때만 때로 발생합니다. 오늘은 Galaxy Nexus의 설정> 개발자 옵션에서 '활동을 유지하지 않음'옵션을 사용하도록 설정하여 문제를 다시 해결했습니다. 응용 프로그램을 시작하고 Home 키를 누른 다음 최근 응용 프로그램 메뉴에서 응용 프로그램을 다시 열고 지금 내 listview의 셀 중 하나를 길게 누르면이 예외가 throw됩니다. 일부 디버그 출력에 의해 onCreateView가 호출 된 적이 없는지를 확인할 수있었습니다. Fragment와 ListView 및 셀 항목이있는 전체 ViewPager가 모두 그려지기 때문에 다소 이상합니다!

ListFragment ACL의 ListFragment은 사용자 정의 레이아웃을 지원하지 않기 때문에 ListFragment을 사용하지 않고 android.support.v4.app.Fragment을 다시 구현했지만 도움이되지 않습니다.

짧은 요약 : 내가의 이벤트를 처리하는 사용자 지정 레이아웃을 길게 누르면 누를 셀에 실재물에 대한 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); 
    } 

앱을 다시 시작할 때 (액티비티가 파괴 된 경우), Fragments와 ListView가있는 ViewPager와 맞춤 레이아웃이 모두 그려지는 것이 이상하지 않습니까? 그러나 IllegalStateException은 listview의 셀을 길게 누르면 뷰가 생성되지 않는다는 것을 알게됩니까?

편집/ 사실, onCreateViewLog.d(Constants.TAG, "onCreateView!!!!"); 출력 방법은 두 번 내가 응용 프로그램합니다 (ViewPager의 각 조각 하나)를 시작하지만 응용 프로그램이 재개 될 때 다음이 다시는 호출되지 것 처음 호출되는 것을 보여줍니다! ? 그게 버그 야, 내가 뭘 잘못했을거야?

답변

4

중요한 부분은 FragmentPagerAdapter (내가 포함하지 않은 것) 인 것처럼 보입니다. 디버깅은 활동이 다시 생성 될 때 getItem()이 호출되지 않음을 보여줍니다. 단편은 다른 방법으로 재생성됩니다. 즉 FragmentPagerAdapter의 구현에서 FragmentManager의 조각에 대한 잘못된 참조가 있음을 의미합니다.

그럼 대신 조각을 찾아야 할 때 findFragmentByTag() (FragmentManager에)을 사용하여 makeFragmentName()을 사용하여 적절한 태그 이름을 얻습니다. 조각을 추가 할 때 FragmentPagerAdapter에서 사용하는 방법입니다. 이것이 안전한 접근인지 여부는 확실하지 않습니다.

관련 문제