質問

私は使っている ViewPager ACLからいくつかを表示します Fragments。最初は、これらすべての断片があります ListFragmentsリストが含まれているので。 2列のテーブルを模倣しようとしているため、リスト内の各要素には2つのオブジェクトの別のリストが含まれています。各セルを長いクリック可能にしたい(リスト項目全体ではない)ため、独自のcolumnlayoutを実装しました(おそらくCelllayoutと呼ぶ必要があります)。各リスト項目には、長いクリック可能で道具の2つの列layoutsが含まれています getContextMenuInfo() どのエンティティがロングクリックされていたかについての情報を返します。この方法は、ViewPagerを調べ、現在のフラグメントを要求し、フラグメントを呼び出して、長いクリックされたビューからエンティティIDを返すように呼び出します。正しい行を取得するために、フラグメントはする必要があります。

getListView().getPositionForView(v)

そして、ここから問題が始まります。時々 getListView() スロー IllegalStateException 「まだ作成されていないコンテンツビュー」と言っています。すなわち onCreateView(...) 呼ばれていません。これは、アプリが再開されたときにのみ発生します。今日、私は「アクティビティを維持しない」オプションを設定> Galaxy Nexusの開発者オプションで有効にすることで、問題を再現することができました。アプリを開始し、家に押してから、最近のアプリメニューからアプリを再開し、リストビューのセルのいずれかをロングクリックすると、この例外がスローされます。いくつかのデバッグ出力によって、私はOnCreateviewが決して呼ばれていないことを確認することができました。 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);
    }

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

編集/実際、a Log.d(Constants.TAG, "onCreateView!!!!"); 出力 onCreateView このメソッドは、アプリを初めて開始するときに2回呼び出されることを示しています(ビューペーガーの各フラグメントに1つ)が、アプリが再開されたときに再び呼び出されることはありません!?それはバグですか、それとも私は何を間違えているのでしょうか?

役に立ちましたか?

解決

重要な部分はそうだったようです FragmentPagerAdapter (私は含めませんでした)。デバッグはそれを示しています getItem() アクティビティが再作成された場合、呼び出されません。フラグメントは他の手段によって再作成されます。それは私の実装を意味します FragmentPagerAdapter のフラグメントへの誤った参照がありました FragmentManager.

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

他のヒント

より良い使用 fragmentStatePagerAdapter そうすれば、それに応じてフラグメントが再現されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top