Używam ViewPager
z listy ACL, aby wyświetlić kilka z Fragment
s. Na początku te Fragmenty, w których wszystkie są ListFragment
s, ponieważ zawierają listę. Próbuję naśladować tabelę 2 kolumn, więc każdy element na liście zawiera inną listę dwóch obiektów. Chcę, aby każda komórka była długo klikalna (a nie cały element listy), dlatego zaimplementowałem własny ColumnLayout (być może powinien on nazywać się CellLayout). Każdy element listy zawiera dwa ColumnLayouts, które są długo klikalne i implementuje getContextMenuInfo()
, aby zwrócić informacje o tym, która encja była długo kliknięta. Ta metoda wyszukuje ViewPager, prosi o bieżący fragment, a następnie wywołuje fragment, aby zwrócić identyfikator encji z widoku, który był długo klikany. Aby uzyskać prawidłowy wiersz, fragment musi wykonać:onCreateView nie jest wywoływany z fragmentem w ViewPager
getListView().getPositionForView(v)
Tutaj zaczyna się problem. Czasami getListView()
wyrzuca IllegalStateException
z napisem "Nie utworzono jeszcze widoku treści". To znaczy. onCreateView(...)
nie został wywołany. Dzieje się tak tylko wtedy, gdy aplikacja jest wznowiona. Dzisiaj udało mi się ponownie stworzyć problem, włączając opcję "Nie wypełniaj aktywności" w Ustawienia> Opcje programisty na moim Galaxy Nexus. Uruchamiam aplikację, naciskam Home, a następnie ponownie otwieram aplikację z ostatniego menu aplikacji, a teraz, jeśli kliknę długo jedną z komórek w moim widoku listy, ten wyjątek zostanie zgłoszony. Przez niektóre wyniki debugowania udało mi się zweryfikować, że onCreateView nigdy nie został wywołany. Co jest dziwne, ponieważ cały ViewPager z jego Fragmentem i ListView oraz jego komórkami są rysowane!
Powiedziano mi na # android-dev, że ListFragment
w ACL nie obsługuje układów niestandardowych, więc ponownie zaimplementowałem mój android.support.v4.app.Fragment
bez używania ListFragment
, ale to nie pomogło.
Krótkie podsumowanie: mam niestandardowy układ, który obsługuje zdarzenie o długim naciśnięciu układ dla celów tworzenia MenuInfo
obiekt zawierający informacje o entitiy w komórce przycisku. Aby znaleźć obiekt zawarty w układzie, ostatecznie wywoływana jest nazwa listview.getPositionForView(View v)
, powodująca niekiedy IllegalStateException
.
Oto mój układ niestandardowy (być może istnieje łatwiejszy sposób zdobyć na ViewPager
niż kopanie w hierarchii widok):
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;
}
}
}
A oto (urywek) 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);
}
Czy to nie jest dziwne, że po wznowieniu aplikacji (jeśli działanie zostało zniszczone), ViewPager wraz z Fragmentami i ListView oraz jego układami niestandardowymi są rysowane. Jednak otrzymuję IllegalStateException
mówiąc, że widok nie został utworzony, jeśli długo naciśnij dowolną komórkę w widoku listy?
edytować/ Faktycznie, Log.d(Constants.TAG, "onCreateView!!!!");
wyjście w onCreateView
pokazuje, że metody jest wywoływana dwa razy po raz pierwszy uruchomić aplikację (po jednym dla każdego fragmentu w ViewPager), ale to nigdy nie jest ponownie wywoływana, gdy aplikacja zostanie wznowione! ? Czy to błąd, czy też coś, co robię źle?