Я использую ViewPager
из ACL, чтобы показать пару Fragment
с.Сначала эти фрагменты, где все ListFragment
s, так как содержат список.Я пытаюсь имитировать таблицу из 2 столбцов, поэтому каждый элемент в списке содержит еще один список из двух объектов.Я хочу, чтобы в каждой ячейке можно было нажимать длинные кнопки (а не весь элемент списка), поэтому я реализовал свой собственный ColumnLayout (возможно, он должен называться CellLayout).Каждый элемент списка содержит два столбца ColumnLayouts, которые можно долго нажимать, и реализует getContextMenuInfo()
для возврата информации о том, какая сущность была долго нажата.Этот метод ищет ViewPager, запрашивает текущий фрагмент, а затем вызывает фрагмент, чтобы вернуть идентификатор объекта из представления, по которому был выполнен длинный щелчок.Чтобы получить правильную строку, необходимо сделать фрагмент:
getListView().getPositionForView(v)
И вот здесь начинается проблема.Иногда getListView()
выбрасывает IllegalStateException
, говоря "Просмотр содержимого еще не создан".Т.е. onCreateView(...)
еще не звонили.Это происходит только иногда, когда приложение возобновляется.Сегодня мне удалось воспроизвести проблему, включив опцию «Не сохранять действия» в меню «Настройки»> «Параметры разработчика» на моем Galaxy Nexus.Я запускаю приложение, нажимаю «Домой», а затем снова открываю приложение из меню недавних приложений, и теперь, если я долго щелкаю по любой из ячеек в моем списке, это исключение выдается.По некоторым выводам отладки мне удалось убедиться, что onCreateView никогда не вызывался.Что довольно странно, потому что весь ViewPager с его Fragment, его ListView и его элементами ячеек нарисован!
Мне сказали на # android-dev, что ListFragment
в ACL не поддерживает пользовательские макеты, поэтому яповторно реализовал мой android.support.v4.app.Fragment
без использования ListFragment
, но это не помогло.
Краткое резюме: У меня есть пользовательский макет, который обрабатывает событие длительного нажатия на макет дляцель создания 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);
}
Не странно ли, что при возобновлении приложения (если действие было уничтожено), то рисуется ViewPager с его фрагментами и ListView, а также пользовательские макеты.И все же я получаю IllegalStateException
, говоря, что представление не было создано, если я долго нажимаю на любую из ячеек в просмотре списка?
edit / Фактически, вывод Log.d(Constants.TAG, "onCreateView!!!!");
в onCreateView
показывает, что методывызывается два раза при первом запуске приложения (по одному для каждого фрагмента в ViewPager), но затем никогда не вызывается при возобновлении работы приложения !?Это ошибка или что я не так делаю?