3

私は楽しみのためにカラーホイールアプリを開発しています。バージョン0.5には、カラーホイールで使用可能なカラーターゲットごとに1つずつ、合計4つのフラグメントで構成されるパレットがあります。フラグメントのUI要素は、カラーホイールのモードに応じて非表示または表示されます。「単色」モードではフラグメントの1つだけが必要ですが、「アクセント付きアナオジック」では4つすべてが必要です。これは、フラグメントがメソッドの一部として構築および表示されるときに検出され、onCreate()その後は変更されません。

レイアウトを改善する次のバージョンでは、4つの「インクルード」XMLレイアウトファイルを設計しました。1つはフラグメントのインスタンスを1つだけ使用し、もう1つは2つを使用します。マスターXMLレイアウトファイルFrameLayoutには、モードが変更されたときに適切な「インクルード」XMLレイアウトファイルを置き換えるポイントが含まれるようになりました。

変更を実行するコードフラグメントは次のとおりです。

private void changeLayout(int layoutID) {
    FragmentManager fMgr = getFragmentManager();
    FragmentTransaction transaction = fMgr.beginTransaction();

    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    FrameLayout frame = (FrameLayout) findViewById(R.id.paletteContainer);
    frame.removeAllViews();

    View view = inflater.inflate(layoutID, frame, false);
    frame.addView(view);
    transaction.commit();

    pFrag = (SwatchFragment.Primary) fMgr.findFragmentById(R.id.base);
    a1Frag = (SwatchFragment.FirstAlternate) fMgr.findFragmentById(R.id.alternate1);
    a2Frag = (SwatchFragment.SecondAlternate) fMgr.findFragmentById(R.id.alternate2);
    cFrag = (SwatchFragment.Complementary) fMgr.findFragmentById(R.id.complementary);    
}

1つ以上のフラグメントが再利用されているため、以下に示す例外があります。では、フラグメントを含むUIの一部を置き換える正しい方法は何ですか?

E/WheelActivityandroid.view.InflateException: Binary XML file line #11: Error inflating class Navigation item selected: pos=1, id=0x00000001
android.view.InflateException: Binary XML file line #11: Error inflating class fragment
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) ~[na:0.0]
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) ~[na:0.0]
        at android.view.LayoutInflater.inflate(LayoutInflater.java:489) ~[na:0.0]
        at android.view.LayoutInflater.inflate(LayoutInflater.java:396) ~[na:0.0]
        at org.dobbo.colour.activity.WheelActivity.changeLayout(WheelActivity.java:321) ~[na:0.0]
        at org.dobbo.colour.activity.WheelActivity.setMode(WheelActivity.java:307) ~[na:0.0]
        at org.dobbo.colour.activity.WheelActivity.onNavigationItemSelected(WheelActivity.java:181) ~[na:0.0]
        at com.android.internal.widget.ActionBarView$1.onItemSelected(ActionBarView.java:148) ~[na:0.0]
        at android.widget.AdapterView.fireOnSelected(AdapterView.java:892) ~[na:0.0]
        at android.widget.AdapterView.access$200(AdapterView.java:49) ~[na:0.0]
        at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:860) ~[na:0.0]
        at android.os.Handler.handleCallback(Handler.java:725) ~[na:0.0]
        at android.os.Handler.dispatchMessage(Handler.java:92) ~[na:0.0]
        at android.os.Looper.loop(Looper.java:137) ~[na:0.0]
        at android.app.ActivityThread.main(ActivityThread.java:5039) ~[na:0.0]
        at java.lang.reflect.Method.invokeNative(Native Method) ~[na:0.0]
        at java.lang.reflect.Method.invoke(Method.java:511) ~[na:0.0]
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) ~[na:0.0]
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) ~[na:0.0]
        at dalvik.system.NativeStart.main(Native Method) ~[na:0.0]
Caused by: java.lang.IllegalArgumentException: Binary XML file line #11: Duplicate id 0x7f0a000b, tag null, or parent id 0x7f0a0010 with anoth
er fragment for org.dobbo.colour.fragment.SwatchFragment$Primary
        at android.app.Activity.onCreateView(Activity.java:4722) ~[na:0.0]
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680) ~[na:0.0]
        ...
4

1 に答える 1

0

1 つ以上のフラグメントが再利用されているため、以下の例外があります。

はい、例外は、既にレイアウトにあるフラグメントと同じ ID (ほとんどの場合) を持つフラグメントを持つ新しいレイアウトをインフレートすることから発生します。これを回避するには、次のようないくつかのオプションがあります。

を使用しFragmentManagerて、現在存在するフラグメントを見つけてレイアウトから削除してから、新しいレイアウトをフラグメントで膨らませることができます。たとえば、現在レイアウトにフラグメントが 1 つしかなく、レイアウトを 2 つのフラグメントで拡張したい場合は、最初に両方のレイアウトに存在するフラグメントを削除します。

getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.fragment1)).commit();
getSupportFragmentManager().executePendingTransactions();
mContainer.removeAllViews();
// inflate thew new layout

しかし、私があなたの状況にあった場合、私はそれを使用しません(主に、静的フラグメントをいじっているためです。これは行うべきではありません)。さて、これらのフラグメントをどのように配置するかはわかりませんが、プレースホルダーコンテナーを保持するマスターレイアウトを作成する方がはるかに理にかなっています (そして、将来的に他のフラグメント関連の問題からあなたを救うことができます) (シンプルFrameLayouts)これらのフラグメントごとに (すべてのフラグメントはonCreateメソッドを使用して、ユーザーがレイアウトを変更するたびに元に戻さないようにします)。この方法では、実行時に必要なフラグメントを非表示にし、必要に応じてラッパー コンテナーのパラメーターを変更するだけで済みます。これにより、アクティビティが構成の破壊に直面する場合 (電話を回転させるときなど) に、無料のフラグメント管理も得られます (フラグメントの状態を維持することも非常に簡単になります)。

于 2012-12-21T19:20:41.097 に答える