it-swarm.com.ru

Назначение фрагментов на вкладки в панели действий с различной ориентацией

У меня есть 3 фрагмента и активность. Я хочу включить вкладки ActionBar и назначить Fragment каждой из 3 вкладок. Как мне правильно это подключить?

ОРИГИНАЛ POST

У меня есть приложение, которое я разрабатываю с помощью приложения Google I/O в качестве руководства. Я реализовал вкладки в ActionBar. Кажется, они работают, пока ориентация планшета не изменится. Например, все 3 вкладки имеют переменную Fragment. Я могу переключаться между ними просто отлично, но когда я меняю ориентацию, независимо от того, какой Fragment у меня был последний просмотр, он остается видимым, но нажатие на вкладки больше не меняет вид ... как будто они отключились. Как и ожидалось, возвращение к исходной ориентации не «исправляет» это.

Я смотрел на сохранение и восстановление состояния, но я не вижу, как это поможет. 

ПРАВКА 

уровень модуля:

Fragment mFragmentA = (Fragment) new AFragmentTab();
Fragment mFragmentB = (Fragment) new BFragmentTab();
Fragment mFragmentC = (Fragment) new CFragmentTab();

У меня есть что-то вроде этого в onCreate действия:

ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);

ActionBar.Tab tabA = actionBar.newTab().setText("text a");
ActionBar.Tab tabB = actionBar.newTab().setText("text b");
ActionBar.Tab tabC = actionBar.newTab().setText("text c");

tabA.setTabListener(this);
tabB.setTabListener(this);
tabC.setTabListener(this);

actionBar.addTab(tabA);
actionBar.addTab(tabB);
actionBar.addTab(tabC);

и TabListener, как это: 

РЕДАКТИРОВАТЬ это удалено

class MyTabListener implements ActionBar.TabListener {
    private Fragment mFragment;

    // Called to create an instance of the listener when adding a new tab
    public MyTabListener(Fragment fragment) {
        mFragment = fragment;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        ft.add(R.id.fragment_content, mFragment, null);
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(mFragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // do nothing
    }
}

ПРАВКА

Я переместил TabListener. Вместо того, чтобы быть отдельным классом, я реализую TabListener на Activity. Затем на методы Selected и Unselected у меня есть что-то вроде:

public void onTabSelected(Tab tab, FragmentTransaction ft) {
    switch (tab.getPosition()) {
    case 0:
        ft.add(R.id.fragment_content, mFragmentA, null);
        break;
    case 1:
        ft.add(R.id.fragment_content, mFragmentB, null);
        break;
    case 2:
        ft.add(R.id.fragment_content, mFragmentC, null);
        break;
    }
}

public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    switch (tab.getPosition()) {
    case 0:
        ft.remove(mFragmentA);
        break;
    case 1:
        ft.remove(mFragmentB);
        break;
    case 2:
        ft.remove(mFragmentC);
        break;
    }
}

Это все еще делает то же самое. Я действительно не знаю, что происходит. 

25
Metallicraft

Похоже, мой ответ можно найти здесь: http://developer.Android.com/resources/samples/ApiDemos/src/com/example/Android/apis/app/FragmentTabs.html

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.Apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.example.Android.apis.app;

import com.example.Android.apis.R;


import Android.app.ActionBar;
import Android.app.ActionBar.Tab;
import Android.app.Activity;
import Android.app.Fragment;
import Android.app.FragmentTransaction;
import Android.os.Bundle;
import Android.widget.Toast;

/**
 * This demonstrates the use of action bar tabs and how they interact
 * with other action bar features.
 */
public class FragmentTabs extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final ActionBar bar = getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        bar.addTab(bar.newTab()
                .setText("Simple")
                .setTabListener(new TabListener<FragmentStack.CountingFragment>(
                        this, "simple", FragmentStack.CountingFragment.class)));
        bar.addTab(bar.newTab()
                .setText("Contacts")
                .setTabListener(new TabListener<LoaderCursor.CursorLoaderListFragment>(
                        this, "contacts", LoaderCursor.CursorLoaderListFragment.class)));
        bar.addTab(bar.newTab()
                .setText("Apps")
                .setTabListener(new TabListener<LoaderCustom.AppListFragment>(
                        this, "apps", LoaderCustom.AppListFragment.class)));
        bar.addTab(bar.newTab()
                .setText("Throttle")
                .setTabListener(new TabListener<LoaderThrottle.ThrottledLoaderListFragment>(
                        this, "throttle", LoaderThrottle.ThrottledLoaderListFragment.class)));

        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }

    public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
        private final Activity mActivity;
        private final String mTag;
        private final Class<T> mClass;
        private final Bundle mArgs;
        private Fragment mFragment;

        public TabListener(Activity activity, String tag, Class<T> clz) {
            this(activity, tag, clz, null);
        }

        public TabListener(Activity activity, String tag, Class<T> clz, Bundle args) {
            mActivity = activity;
            mTag = tag;
            mClass = clz;
            mArgs = args;

            // Check to see if we already have a fragment for this tab, probably
            // from a previously saved state.  If so, deactivate it, because our
            // initial state is that a tab isn't shown.
            mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
            if (mFragment != null && !mFragment.isDetached()) {
                FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
                ft.hide(mFragment);
                ft.commit();
            }
        }

        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
                ft.add(Android.R.id.content, mFragment, mTag);
            } else {
                ft.show(mFragment);
            }
        }

        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if (mFragment != null) {
                ft.hide(mFragment);
            }
        }

        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT).show();
        }
    }
}
22
Metallicraft

Ссылка, предоставленная @Metallicraft, мертва, так что здесь есть некоторая помощь для тех, кто все еще натыкается на этот пост. Перейти здесь для помощи с реализацией вкладок.

Чтобы увидеть/прочитать оригинальный пример, вы можете перейти в следующую папку, если вы установили среду разработки Android: Android-sdk\samples\Android-14\ApiDemos\src\com\example\Android\apis\app\FragmentTabs.Java

Также, если у вас есть проблемы с частичным перекрытием фрагментов после изменения ориентации, это правильно связано с сохраненным состоянием экземпляра. Вот копия вставки из учебника Google , которая объясняет проблему с перекрытием фрагментов и как ее избежать:

import Android.os.Bundle;
import Android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);

        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            // Create an instance of ExampleFragment
            HeadlinesFragment firstFragment = new HeadlinesFragment();

            // In case this activity was started with special instructions from an Intent,
            // pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());

            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
}
7
Warpzit

Создайте новый пример проекта Android, выберите образец Support4Demos. Вы найдете образец FragmentTabs там.

2
azevik

У меня была более или менее та же проблема, но представленные выше решения, похоже, не сработали в моей ситуации. В конце концов я нашел следующее решение:

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if (mFragment == null) {
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.replace(Android.R.id.content, mFragment, mTag); // Use replace iso add
        }
        else {
            ft.attach(mFragment);
        }
    }
1
Boeboe
        @Override
        public void onTabSelected(ActionBar.Tab tab, Android.support.v4.app.FragmentTransaction fragmentTransaction) {
            // Check if the fragment is already initialized

            if (mFragment == null) {
                // If not, instantiate and add it to the activity
               // Toast.makeText(getApplicationContext(),"TAb "+tab.getPosition(),Toast.LENGTH_LONG).show();
                if(tab.getPosition() == 1) {
                   mFragment = new HolderFragment();
                    fragmentTransaction.add(Android.R.id.content, mFragment, mTag);
                }
                else if(tab.getPosition() == 0)
                {
                    mFragment = new FragmentKnowledge();
                    fragmentTransaction.add(Android.R.id.c`enter code here`ontent, mFragment, mTag);

                }
                /*else
                {

                     mFragment = Fragment.instantiate(mActivity, mClass.getName());
                    fragmentTransaction.add(Android.R.id.content, mFragment, mTag);
                }
*/
            } else {
                // If it exists, simply attach it in order to show it
                fragmentTransaction.attach(mFragment);
            }
        }
0
Aye Su Naing

Это отлично сработало для меня! У меня была проблема, когда действия пересекались каждый раз, когда я менял вкладки:

        mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
        if (mFragment != null && !mFragment.isDetached()) {
            FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
            ft.detach(mFragment);
            ft.commit();

Еще раз спасибо!

0
saman0suke