草庐IT

Android - 来自支持库的 fragment 与 4.3 平台不兼容

coder 2023-12-16 原文

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


我想在 2.3.3 平台上制作一个带有 fragment 切换的动态导航选项卡,就像 API Demo 所做的那样。


在 2.3.3 平台上一切正常,但是当我在 4.3 平台上查看相同的 Activity 时,我发现有些东西很奇怪。

SupportFragmentManagement 无法分离 fragment ,似乎选项卡选择回调未正确执行;

下面的图片显示了我的演示是如何进行的

这是我的代码:

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;

//使用来自支持库的 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;
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;
        }
    }
}

但是当我将所有support api更改为regular 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;

// use the api from default platform(only in v11 and later)

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;

@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;
        }
    }
}

我可以使用 (values-v14/classes.xml) 和下面的代码制作兼容版本

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

但我还是想知道support library版本是怎么回事,谁能帮我解决这个问题?

最佳答案

谷歌发布 Nexus 5 和一个新的支持库 (v19),这个版本修复了这个错误

关于Android - 来自支持库的 fragment 与 4.3 平台不兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19667677/

有关Android - 来自支持库的 fragment 与 4.3 平台不兼容的更多相关文章

  1. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  2. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  3. ruby - 可以正常中断的来自 Rake 的长时间运行的 shell 命令? - 2

    在几个项目中,我希望有一个类似rakeserver的rake任务,它将通过任何需要的方式开始为该应用程序提供服务。这是一个示例:task:serverdo%x{bundleexecrackup-p1234}end这行得通,但是当我准备停止它时,按Ctrl+c并没有正常关闭;它中断了Rake任务本身,它说rakeaborted!并给出堆栈跟踪。在某些情况下,我必须执行Ctrl+c两次。我可能可以用Signal.trap写一些东西来更优雅地中断它。有没有更简单的方法? 最佳答案 trap('SIGINT'){puts"Yourmessa

  4. ruby-on-rails - 不兼容的库版本 : nokogiri. bundle 需要 8.0.0 或更高版本,但 libiconv.2.dylib 提供 7.0.0 版本 - 2

    为了在我的mac上为一个rails项目安装mysql,我遵循了安装Homebrew软件和删除mac端口的在线建议。这是问题开始的地方。rails项目不会构建,我得到这个:[rake--prereqs]rakeaborted!dlopen(/Users/Parker/.rvm/gems/ruby-1.9.3-p448/gems/nokogiri-1.6.0/lib/nokogiri/nokogiri.bundle,9):Librarynotloaded:/opt/local/lib/libiconv.2.dylibReferencedfrom:/Users/Parker/.rvm/gem

  5. ruby - ruby 中的同一个程序如何接受来自用户的输入以及命令行参数 - 2

    我的ruby​​脚本从命令行参数获取某些输入。它检查是否缺少任何命令行参数,然后提示用户输入。但是我无法使用gets从用户那里获得输入。示例代码:test.rbname=""ARGV.eachdo|a|ifa.include?('-n')name=aputs"Argument:#{a}"endendifname==""puts"entername:"name=getsputsnameend运行脚本:rubytest.rbraghav-k错误结果:test.rb:6:in`gets':Nosuchfileordirectory-raghav-k(Errno::ENOENT)fromtes

  6. ruby-on-rails - Rails 3,在RAILS_ROOT上方显示来自本地文件系统的jpg图片 - 2

    我正在尝试找出一种方法来显示来自不在RAILS_ROOT下(在RedHat或Ubuntu环境中)的已安装文件系统的图像。我不想使用符号链接(symboliclink),因为这个应用程序实际上是通过Tomcat部署的,而当我关闭Tomcat时,Tomcat会尝试跟随符号链接(symboliclink)并删除挂载中的所有图像。由于这些文件的数量和大小,将图像放在public/images下也不是一种选择。我查看了send_file,但它只会显示一张图片。我需要在一个格式良好的页面中显示6个请求的图像。由于膨胀,我宁愿不使用Base64编码,但我不知道如何将图像数据与呈现的页面一起传递下去。

  7. ruby - 如何使用 readline 支持重新安装 ruby​​? - 2

    我已经按照https://github.com/wayneeseguin/rvm#installation上的说明通过RVM安装了Ruby.有关信息,我有所有文件(readline-5.2.tar.gz、readline-6.2.tar.gz、ruby-1.9.3-p327.tar.bz2、rubygems-1.8.24.tgz、wayneeseguin-rvm-stable.tgz和yaml-0.1.4.tar.gz)在~/.rvm/archives目录中,我不想在任何目录中重新下载它们方式。当我这样做时:sudo/usr/bin/apt-getinstallbuild-essent

  8. ruby-on-rails - "undefined method ` stub_request '"访问 RSpec 支持文件中的方法时 - 2

    我的Ruby-on-Rails项目中有以下文件结构,用于规范:/spec/msd/serviceservice_spec.rb/support/my_modulerequests_stubs.rb我的request_stubs.rb有:moduleMyModule::RequestsStubsmodule_functiondeflist_clientsurl="dummysite.com/clients"stub_request(:get,url).to_return(status:200,body:"clientsbody")endend在我的service_spec.rb我有:re

  9. ruby - Ruby 是否支持逐字字符串? - 2

    Ruby是否支持(找不到更好的词)非转义(逐字)字符串?就像在C#中一样:@"c:\ProgramFiles\"...或者在Tcl中:{c:\ProgramFiles\} 最佳答案 是的,您需要在字符串前加上%前缀,然后是描述其类型的单个字符。你想要的是%q{c:\programfiles\}。镐书很好地涵盖了这一点here,部分是通用分隔输入。 关于ruby-Ruby是否支持逐字字符串?,我们在StackOverflow上找到一个类似的问题: https:/

  10. ruby - 在 Ruby 1.8 中支持 Ruby 1.9 的哈希语法 - 2

    我正在编写一个Rubygem,在我的代码中使用{key:'value'}哈希语法。我的测试都在1.9.x中通过,但我(可以理解)在1.8.7中得到syntaxerror,unexpected':',expecting')'。是否有支持1.8.x的最佳实践?我是否需要使用我们的老friend=>重写代码,还是有更好的策略? 最佳答案 我认为你运气不好,如果你想支持1.8,那么你必须使用=>。像往常一样,我会提到在1.9的某些情况下您必须使用=>:如果键不是一个符号。请记住,任何对象(符号、字符串、类、float……)都可以是Ruby哈

随机推荐