Android 在 Fragment 中替换 Fragment

Posted

技术标签:

【中文标题】Android 在 Fragment 中替换 Fragment【英文标题】:Android Replace Fragment within a Fragment 【发布时间】:2012-12-31 23:17:39 【问题描述】:

我有一个名为 “MeinProfilFragment” 的片段。 还有一个处理 ActionBar-Tabs 逻辑的 MainActivity。

“MeinProfilFragment”中,我已经为“登录进程”添加了逻辑

用户登录成功后我想显示另一个 布局。

怎么办?是否可以在片段中替换片段? 还是我必须为 UI-Updates 调用 MainActivity ?

这是“MainActivity”的代码:

public class MainActivity extends Activity 

public static int selectedTab;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ActionBar actionBar = getActionBar();

    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);    
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(false);

    Tab meinProfil = actionBar.newTab().setText("Mein Profil");
    TabListener<MeinProfilFragment> tabListenerMeinProfil = new TabListener<MeinProfilFragment>(this,"Mein Profil",MeinProfilFragment.class);
    meinProfil.setTabListener(tabListenerMeinProfil);
    actionBar.addTab(meinProfil);

    Tab mitglieder = actionBar.newTab().setText("Mitglieder");
    TabListener<MitgliederFragment> tabListenerMitglieder = new TabListener<MitgliederFragment>(this,"Mitglieder",MitgliederFragment.class);
    mitglieder.setTabListener(tabListenerMitglieder);
    actionBar.addTab(mitglieder);

    Tab dinner = actionBar.newTab().setText("Dinner");
    TabListener<DinnerFragment> tabListenerDinner = new TabListener<DinnerFragment>(this,"Dinner",DinnerFragment.class);
    dinner.setTabListener(tabListenerDinner);
    actionBar.addTab(dinner);

    Tab community = actionBar.newTab().setText("Community");
    TabListener<CommunityFragment> tabListenerCommunity = new TabListener<CommunityFragment>(this,"Community",CommunityFragment.class);
    community.setTabListener(tabListenerCommunity);
    actionBar.addTab(community);

    if(savedInstanceState != null)
        actionBar.setSelectedNavigationItem(savedInstanceState.getInt("selectedTab"));
    



private static class TabListener<T extends Fragment> implements ActionBar.TabListener

    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public TabListener(Activity activity,String tag,Class<T> clz) 
         mActivity = activity;
         mTag = tag;
         mClass = clz; 
    
    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) 
        selectedTab = tab.getPosition();
        Fragment prevFragment;
        FragmentManager fm = mActivity.getFragmentManager();
        prevFragment = fm.findFragmentByTag(mTag); 
        if (prevFragment != null)  
            mFragment = prevFragment; 
        
        if(mFragment == null)
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment,mTag);
        else
            ft.attach(mFragment);
           
     
    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) 
        selectedTab = tab.getPosition();
        if(mFragment != null)
             ft.detach(mFragment);
        else
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment,mTag);
        
    
    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) 
        selectedTab = tab.getPosition();
       

@Override
protected void onSaveInstanceState(Bundle outState) 
    super.onSaveInstanceState(outState);
    outState.putInt("selectedTab", selectedTab);
   

这是 MeinProfilFragment:

public class MeinProfilFragment extends Fragment implements OnClickListener

EditText LoginEmail;
EditText LoginPassw;
Button LoginButton;
public boolean loggedIn = false;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) 
    View view =  inflater.inflate(R.layout.mein_profil_fragment,container, false);
    LoginEmail = (EditText) view.findViewById(R.id.login_email_input);
    LoginPassw = (EditText) view.findViewById(R.id.login_passwort_input);
    LoginButton  = (Button) view.findViewById(R.id.login_submit);
    LoginButton.setOnClickListener(this);
    return view;


@Override
public void onClick(View arg0) 
    switch(arg0.getId())
    
        case R.id.login_submit:
            // Get Input Values:
            String login_email = LoginEmail.getText().toString();
            String login_passw = LoginPassw.getText().toString();
            if(login_email.length()<6 || login_passw.length()<4)
                return;
               
            Log.i("TEST","onClick: E-Mail: "+login_email+" \n Passwort: "+login_passw);
            new Login().execute(login_email,login_passw);
        break;
    


private class Login extends AsyncTask<String,Void,JSONObject>

    @Override
    protected JSONObject doInBackground(String... params) 
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost("xxxx");
        try
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("mitglied_email",params[0]));
            nameValuePairs.add(new BasicNameValuePair("mitglied_passwort",params[1]));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            String line = reader.readLine();
            JSONObject jsonData = new JSONObject(line);
            return jsonData;
        catch(Exception e)
            e.printStackTrace();
        
        return null;
    

    @Override
    protected void onPostExecute(JSONObject result) 
        super.onPostExecute(result);
        updateUi(result);
       


public void updateUi(JSONObject result)

    try 
        Log.i("TEST",result.getString("logged_in"));
        String loggedInFlag = result.getString("logged_in");
        if(loggedInFlag.equals("true"))
            // Richtige Angaben:
            Log.i("TEST","loggedInFlag EQ TRUE");
            loggedIn = true;

            // Here i want to replace this current fragment with another called e.g "ProfileFragment"

        else
            // Falsche Angaben:
            Log.i("TEST","loggedInFlag EQ FALSE");
            loggedIn = false;
        

     catch (JSONException e) 
        e.printStackTrace();
    

updateUi() 方法中,我想显示/膨胀另一个 UI。

怎么办? 有没有办法“重启”片段然后 在 onCreateView() 中膨胀另一个 Fragment-Layout。

或者可以将 Fragment-Layout 替换为另一个 Fragment-Layout 在 Fragment 内?

最佳做法是什么?

【问题讨论】:

【参考方案1】:

你可以用这个替换片段

FragmentManager fragmentManager2 = getFragmentManager();
FragmentTransaction fragmentTransaction2 = fragmentManager2.beginTransaction();
DetailFragment fragment2 = new DetailFragment();
fragmentTransaction2.addToBackStack("xyz");
fragmentTransaction2.hide(MeinProfilFragment.this);
fragmentTransaction2.add(android.R.id.content, fragment2);
fragmentTransaction2.commit();

【讨论】:

替换后忘记将新的fragment添加到backstack,'fragmentTransaction2.addToBackStack(null); 嗨,好的...我已将上面的代码添加到我的 updateUi() 方法中。但是要放入 fragmentTransaction2.replace(R.id.xxx, fragment2); ? R.id.fragmentid?我没有在 xml 文件中定义 Fragment。 @SanketKachhela 这是真的,我添加它只是为了完成。 @JulianFürderer 您在 XML 中定义了什么?框架布局? 我试图将***“LinearLayout”放到replace() 的第一个参数中......这有效,但旧片段并没有消失,-片段2的文本在底部变得可见.

以上是关于Android 在 Fragment 中替换 Fragment的主要内容,如果未能解决你的问题,请参考以下文章

为啥android fragment 不调用 oncreateview方法

Android中FragmentPagerAdapter对Fragment的缓存

Android Fragment 基本介绍

Android Fragment 基本介绍

如何在Fragment中使用Actionbar-Android开发问答

Android开发之漫漫长途 Fragment番外篇——TabLayout+ViewPager+Fragment