11

私が直面しているシナリオは、私のアプリケーションでは、シングルペインデュアルペインスタイルのレイアウトです。画面間で可能なナビゲーション操作を個別に処理するのではなく、レイアウトのスタイルごとに、目的の画面が表示されたときにレイアウトを正しく設定する機能を使用しています。

これは基本的にアプリの各画面のステートメントであり、各レイアウトスタイルを処理するために各画面にswitchネストされたステートメントがあります。switchこれは私がコードで話していることです:

protected void setupScreen() {
    switch(currentScreen) {
    case SCREEN_ONE:
        switch(currentLayout) {
        case SINGLE_PANE:
            // Perform actions to setup the screen
            break;
        case DUAL_PANE:
            // Perform actions to setup the screen
            break;
        }
        break;
    case SCREEN_TWO:
        switch(currentLayout) {
        case SINGLE_PANE:
            // Perform actions to setup the screen
            break;
        case DUAL_PANE:
            // Perform actions to setup the screen
            break;
        }
        break
    // ... etc ....
    }
}

画面を設定するためのアクションを実行したいセクションでは、これは次の基本的な3つの操作で構成されています。

// Create the fragments if necessary
if (screenFragment == null) {
    screenFragment = new myFragment();
}

// Remove the existing fragments from the layout views
// HOW???

// Add the fragments for this screen to the view
getSupportFragmentManager().beginTransaction().add(pane1.getId(), myFragment, "myFragment").commit();

ご覧のとおり、私が苦労しているのは、2番目のステップの実行方法です。削除したいものを正確に知らずに、特定のからすべてを削除するにはどうすればよいですか?私が見つけた最も近いものは、すべての場合にこれを正常に実行することです、それが判明した場合は、を同じフラグメントに置き換えています。この場合、すべてを削除してから追加するわけではなく(ドキュメントが示唆しているように)、削除するように見えます。これは互換性ライブラリの使用に関する問題ですか、それとも使用すべき方法ではありませんか?FragmentViewFragmentTransaction.replace()FragmentFragmentTransaction.replace()

いずれにせよ、どうすればこれを行うことができますか?すべてのフラグメントを調べてデタッチする関数をコーディングする必要がありますか、それとも「ツーインワンremoveAllFragments()」関数が主張することの前半を実行する方法はありFragmentTransaction.replace()ますか?

4

5 に答える 5

7

典型的なメカニズムは、 を使用することFragmentManager.findFragmentByTag()です。これを使用して、タグをフラグメント (または ID の代わり) に追加します。このようにして、現在管理されているフラグメントを特定できます。次に、現在のフラグメントへのハンドルを取得したら (findFragmentByTag が null 以外を返す)、FragmentManager.beginTransaction()FragmentTransaction を開始し、必要なフラグメントを削除/追加するために使用できます。このように作業すると、保持したいフラグメントの「再追加」プロセスを回避できます。

私がおそらく行うことは、次のようなコードを作成することです:(疑似コードの警告)

Fragment pane1 = FragmentManager.findFragmentByTag("myFragmentPane1");
Fragment pane2 = FragmentManager.findFragmentByTag("myFragmentPane2");

setupScreen(pane1, pane2);

「すべてを 1 つのクラスにする」のではなく、クラスのサブクラスも考慮する必要があります。Martin Fowler のReplace Conditional with Subclassのかなり明白なケースがあります。そうしないと、別の画面を追加したときに、これを管理するのが非常に難しくなるのではないかと心配しています。

于 2013-02-08T02:02:27.353 に答える
3

android.support.v4.app.Fragmentを使用すると、次のことができます。

List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
    for (Fragment fragment : fragments) {
        getSupportFragmentManager().beginTransaction().remove(fragment).commit();
    }
}
于 2016-04-30T09:52:13.600 に答える
1

これFragmentTransaction.replace()は正しい操作であり、正しく動作するはずです。使用時のみ動作しないので、この互換ライブラリのバグだとしかActionBarSherlock思えません。SherlockFragmentActivity

以下のコードを使用して、Android on API11+、Android 互換性ライブラリ、および ActionBarSherlock を介して目的の動作を実装することで、これを確認しました。最後のインスタンスでのみ壊れます。

package com.test.test;

import com.actionbarsherlock.app.SherlockFragmentActivity;

import android.os.Bundle;
import android.content.Context;
import android.graphics.Color;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

public class MainActivity extends SherlockFragmentActivity {
  // Consistent fragment instance
    myFragment myFrag = null;

    // Views
    FrameLayout fl = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.VERTICAL);

        Button b = new Button(this);
        b.setText("Repeat");
        b.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                // Reattach the same fragment
                getSupportFragmentManager().beginTransaction().replace(fl.getId(), myFrag).commit();

            }
        });

        fl = new FrameLayout(this);
        fl.setId(200);
        fl.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

        myFrag = new myFragment();
        getSupportFragmentManager().beginTransaction().add(fl.getId(), myFrag).commit();

        ll.addView(b);
        ll.addView(fl);

        setContentView(ll);
    }

    public static class myFragment extends Fragment {

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            TextView tv = new TextView(getActivity());
            tv.setText("My fragment");
            tv.setGravity(Gravity.CENTER);
            tv.setBackgroundColor(Color.RED);

            return tv;
        }
    }

}
于 2013-02-09T06:08:23.383 に答える
0

これは多かれ少なかれ私がこれを処理した方法です。すべてのフラグメントに次のようなインターフェースを実装させます。

public interface NamedFragment{

    public FragmentName getFragmentName();

}

フラグメントに対応する列挙型を作成します。

public enum FragmentName{

    SOME_FRAGMENT,
    SOME_OTHER_FRAGMENT;

}

次に、フラグメント切り替えアクティビティで:

// Get the manager and transaction separately so you can use both: 
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction ft = fragmentManager.beginTransaction();

// Get a reference to the fragment(s) currently in the container(s)
    Fragment currentFragment = fragmentManager.findFragmentById(position);

    FragmentName cFragmentName =
            ((NamedFragment) currentFragment).getFragmentName();
    Fragment nextFragment =
            Fragment.instantiate(this, some_new_fragment_string);
    FragmentName nFragmentName =
            ((NamedFragment) nextFragment).getFragmentName();
// Compare the "names"
    if(cFragmentName != nFragmentName){
        ft.replace(position, nextFragment);
    }

仕様に合わせて少し変更する必要があります。

于 2013-02-08T01:57:34.113 に答える