Android - 支持库中的片段与4.3平台不兼容

HxH*_*obb 5 android android-fragments android-actionbar android-support-library

我在使用支持库时遇到了一个奇怪的问题.


我想制作一个动态导航标签,片段在2.3.3平台上切换,就像做了什么API Demo.

在此输入图像描述


2.3.3平台上的一切都很顺利,但是当我在4.3平台上查看相同的活动时,我发现了一些非常奇怪的东西.

SupportFragmentManagement不能分离的片段,好像选项卡中选择回调没有正确执行;

以下图片展示了我的演示如何进行 在此输入图像描述

这是我的代码:

package net.zengweizhi.android.gettingstarted.lesson05.test;
import net.zengweizhi.android.gettingstarted.R;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
Run Code Online (Sandbox Code Playgroud)

//使用支持库中的api

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
import android.support.v7.app.ActionBar.TabListener;
import android.support.v7.app.ActionBarActivity;
Run Code Online (Sandbox Code Playgroud)
public class NavigationTabsWithFragmentsV9 extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_navigation_tabs, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.actionButton_addTab:
            addTab();
            break;
        case R.id.actionButton_removeTab:
            removeTab();
            break;
        default:
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    private int mTabSeq = 0;

    private void addTab(){
        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        mTabSeq++;

        Tab tab = getSupportActionBar().newTab();
        tab.setText("TAB " + mTabSeq);
        tab.setTabListener(new MyTabListener(this));
        getSupportActionBar().addTab(tab);
    }

    private void removeTab(){
        Tab tab = getSupportActionBar().getSelectedTab();
        getSupportActionBar().removeTab(tab);

        Fragment fragment = getSupportFragmentManager().findFragmentByTag(tab.getText().toString());
        getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        if( getSupportActionBar().getTabCount() == 0 ){
            getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        }
    }

    private static final class MyTabListener  implements TabListener {
        private NavigationTabsWithFragmentsV9 mActivity;
        public MyTabListener(NavigationTabsWithFragmentsV9 activity /*,Fragment fragment*/){
            mActivity = activity;
        }

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            // Do nothing
        }

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            Object obj = tab.getTag();
            if( null == obj ){
                Bundle args = new Bundle();
                args.putString(SimpleFragment.EXTRA_OUTPUT_MESSAGE, tab.getText().toString());
                Fragment fragment = Fragment.instantiate(mActivity, SimpleFragment.class.getName(), args);
                ft.add(android.R.id.content, fragment, tab.getText().toString());

                tab.setTag(obj = fragment);
            }

            ft.attach((Fragment)obj);
        }

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if( null != mActivity.getSupportFragmentManager().findFragmentByTag(tab.getText().toString()) ){
                ft.detach((Fragment)tab.getTag());
            }
        }

    }

    public static final class SimpleFragment extends Fragment {
        public static final String EXTRA_OUTPUT_MESSAGE = "output_message";

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View fragmentView = inflater.inflate(R.layout.fragment_simple, container, false);

            String outputMesasge = null;
            if( null != getArguments() ){
                outputMesasge = getArguments().getString(EXTRA_OUTPUT_MESSAGE);
            }
            if( null == outputMesasge || 0 == outputMesasge.trim().length() ){
                outputMesasge = getString(R.string.demo_text);
            }
            TextView textView = (TextView) fragmentView.findViewById(R.id.textView_simpleFragmentOutput);
            textView.setText(outputMesasge);

            return fragmentView;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我改变一切support apiregular api(default platform api),一切顺利的4.3平台(但是这一次不兼容2.3.3平台);

在此输入图像描述

这是代码(除ActionBar和Fragment API之外没什么区别)

package net.zengweizhi.android.gettingstarted.lesson05.test;

import net.zengweizhi.android.gettingstarted.R;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
Run Code Online (Sandbox Code Playgroud)

//使用默认平台的api(仅限v11及更高版本)

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;
import android.app.Fragment;
import android.app.FragmentTransaction;
Run Code Online (Sandbox Code Playgroud)

@SuppressLint( "NewApi")

public class NavigationTabsWithFragmentsV14 extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_navigation_tabs, menu);
        return super.onCreateOptionsMenu(menu);
    }

    private int mTabSeq = 0;

    private void addTab(){
        getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        mTabSeq++;

        Tab tab = getActionBar().newTab();
        tab.setText("TAB " + mTabSeq);
        tab.setTabListener(new MyTabListener(this));
        getActionBar().addTab(tab);
    }

    private void removeTab(){
        Tab tab = getActionBar().getSelectedTab();
        getActionBar().removeTab(tab);

        Fragment fragment = getFragmentManager().findFragmentByTag(tab.getText().toString());
        getFragmentManager().beginTransaction().remove(fragment).commit();
        if( getActionBar().getTabCount() == 0 ){
            getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.actionButton_addTab:
            addTab();
            break;
        case R.id.actionButton_removeTab:
            removeTab();
            break;
        default:
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    private static final class MyTabListener  implements TabListener {
        private NavigationTabsWithFragmentsV14 mActivity;
        public MyTabListener(NavigationTabsWithFragmentsV14 activity /*,Fragment fragment*/){
            mActivity = activity;
        }

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            // Do nothing
        }

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            Object obj = tab.getTag();
            if( null == obj ){ // initialize fragment to tab
                Bundle args = new Bundle();
                args.putString(SimpleFragment.EXTRA_OUTPUT_MESSAGE, tab.getText().toString());
                Fragment fragment = Fragment.instantiate(mActivity, SimpleFragment.class.getName(), args);
                ft.add(android.R.id.content, fragment, tab.getText().toString());

                tab.setTag(obj = fragment);
            }
            ft.attach((Fragment)obj);
        }

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if( null != mActivity.getFragmentManager().findFragmentByTag(tab.getText().toString()) ){
                ft.detach((Fragment)tab.getTag());
            }
        }
    }

    public static final class SimpleFragment extends Fragment {
        public static final String EXTRA_OUTPUT_MESSAGE = "output_message";

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View fragmentView = inflater.inflate(R.layout.fragment_simple, container, false);

            String outputMesasge = null;
            if( null != getArguments() ){
                outputMesasge = getArguments().getString(EXTRA_OUTPUT_MESSAGE);
            }
            if( null == outputMesasge || 0 == outputMesasge.trim().length() ){
                outputMesasge = getString(R.string.demo_text);
            }
            TextView textView = (TextView) fragmentView.findViewById(R.id.textView_simpleFragmentOutput);
            textView.setText(outputMesasge);

            return fragmentView;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以使用(values-v14/classes.xml)和以下代码创建兼容版本

try {
    Class<?> clazz = Class.forName(getString(R.string.class_navigationTabsAndFragmentsActivity));
    startActivity(clazz);
} catch (ClassNotFoundException ex) {
    showTextByToast(ex.getMessage());
}
Run Code Online (Sandbox Code Playgroud)

但是我仍然想知道support library版本中发生了什么,有人能帮我解决这个问题吗?

HxH*_*obb 2

Google 发布 Nexus 5 和新的支持库(v19),该版本修复了这个 bug 在此输入图像描述