java - 设备旋转时如何更改不同标记的布局?

标签 java android android-layout android-studio android-fragments

描述

我有一个 Activity 在垂直方向,其中包含两个选项卡 (TabLayout) 和 fragment ,它们随着 Viewpager 的变化而变化。

MainActivity.java

public class MainActivity extends AppCompatActivity {

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

        ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        // Assign created adapter to viewPager
        viewPager.setAdapter(new TabsExamplePagerAdapter(getSupportFragmentManager()));

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        // This method setup all required method for TabLayout with Viewpager
        tabLayout.setupWithViewPager(viewPager);
    }

    public class TabsExamplePagerAdapter extends FragmentPagerAdapter {
        // As we are implementing two tabs
        private static final int NUM_ITEMS = 2;

        public TabsExamplePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        // For each tab different fragment is returned
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new TabOneFragment();
                case 1:
                    return new TabTwoFragment();
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            return NUM_ITEMS;
        }

        @Override
        public CharSequence getPageTitle(int position) { 
            return "Tab " + (position + 1);
        }
    }
}  

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:tabTextColor="#ffffff"
        app:tabIndicatorColor="#fbff3a"
        app:tabSelectedTextColor="#fbff3a"
        app:tabIndicatorHeight="5dp"
        android:elevation="4dp"
        app:tabGravity="fill"
        app:tabMaxWidth="0dp" />

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>  

在每个选项卡中我都有一个 fragment 。

TabOneFragment.java(TabTwoFragment 类似):

public class TabOneFragment extends Fragment {

    // Required empty public constructor
    public TabOneFragment() { }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_tab_one, container, false);
    }
}

fragment_one_tab.xml(fragment_one_tab.xml 类似)

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="innovatecode.com.tabexample.TabOneFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="18dp"
        android:text="@string/tab_one" />

</FrameLayout>

我的结果很简单:

enter image description here

我的问题

当我的设备旋转到水平位置时,我想得到以下结果: enter image description here

我为水平标记(land)创建 xml:

active_main.xml(陆地)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

     <FrameLayout 
            android:id="@+id/fragment_left"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />

      <FrameLayout
            android:id="@+id/fragment_right"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />

</LinearLayout>

但我不知道如何更改我的代码来获得这个结果。我不太擅长使用 fragment 。

最佳答案

首先,您可以通过将 fragment 直接添加到布局文件(在“res/layout-land”下)来改进横向布局:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

     <fragment
            android:name="innovatecode.com.tabexample.TabOneFragment"
            android:id="@+id/fragment_left"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />

      <fragment
            android:name="innovatecode.com.tabexample.TabTwoFragment"
            android:id="@+id/fragment_right"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />

</LinearLayout>

您可以阅读主题 here 的移动.

对于代码部分,您可以利用横向和纵向布局的不同特征来在代码中相应的逻辑之间进行切换。例如:

 public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        if (findViewById(R.id.tab_layout) != null) {
            setUpPortraitLayout();
        } else {
            setUpLandscapeLayout();
        }
    }

    private void setUpPortraitLayout() {
        ViewPager viewPager = findViewById(R.id.pager);
        // Assign created adapter to viewPager
        viewPager.setAdapter(new TabsExamplePagerAdapter(getSupportFragmentManager()));

        TabLayout tabLayout = findViewById(R.id.tab_layout);
        // This method setup all required method for TabLayout with Viewpager
        tabLayout.setupWithViewPager(viewPager);
    }

    private void setUpLandscapeLayout() {
        // Note: with the layout definition suggested above you don't
        // need any manual processing to set-up your layout for landscape
        // but you still may have some extra set-up (initial binding, etc).
        tabOneFragment = (TabOneFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_left);
        tabTwoFragment = (TabTwoFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_right);
        // ...
    }
}

您可以通过“setArguments() ”方法将保存的参数传递给您的 fragment 。或者考虑使用 fragment 的“onSaveInstanceState()”方法(而不是您现在使用的 Activity )。

替代方法:在横向和纵向情况下动态添加 fragment 。它基于您的代码。我认为某些方面是有争议的(我可能是错的),但改变方向就意味着重写整个事情。但它最终应该会起作用。

res/layout-land/active_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

     <FrameLayout 
            android:id="@+id/fragment_left"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />

      <FrameLayout
            android:id="@+id/fragment_right"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />

</LinearLayout>

MainActivity.java(基于您通过要点共享的代码)

public class MainActivity extends AppCompatActivity {
    private Fragment tabOneFragment;
    private Fragment tabTwoFragment;

    private ViewPager viewPager;

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

        setContentView(R.layout.activity_main);

        if (savedInstanceState != null) {
            //Restore the fragment's instance
            tabOneFragment = (TabOneFragment) getSupportFragmentManager().getFragment(
                    savedInstanceState, "tabOneFragment");
            tabTwoFragment = (TabTwoFragment) getSupportFragmentManager().getFragment(
                    savedInstanceState, "tabTwoFragment");
        } else {
            tabOneFragment = new TabOneFragment();
            tabTwoFragment = new TabTwoFragment();
        }

        if (findViewById(R.id.tab_layout) != null) {
            setUpPortraitLayout();
        } else {
            setUpLandscapeLayout();
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        getSupportFragmentManager().putFragment(outState, "tabOneFragment", tabOneFragment);
        getSupportFragmentManager().putFragment(outState, "tabTwoFragment", tabTwoFragment);
    }

    private void setUpPortraitLayout() {
        viewPager = (ViewPager) findViewById(R.id.pager);
        // Assign created adapter to viewPager
        viewPager.setAdapter(new TabsPagerAdapter(getSupportFragmentManager()));

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        // This method setup all required method for TabLayout with Viewpager
        tabLayout.setupWithViewPager(viewPager);
    }

    private void setUpLandscapeLayout() { 
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_left, tabOneFragment);
        transaction.replace(R.id.fragment_right, tabTwoFragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

    private class TabsPagerAdapter extends FragmentPagerAdapter {
        // As we are implementing two tabs
        private static final int NUM_ITEMS = 2;

        public TabsPagerAdapter(FragmentManager fragmentManager) {
            super(fragmentManager);
        }

        @Override
        // For each tab different fragment is returned
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return tabOneFragment;

                case 1:
                    return tabTwoFragment;

                default:
                    throw new IllegalStateException("Invalid tab index");
            }
        }

        @Override
        public int getCount() { return NUM_ITEMS; }

        @Override
        public CharSequence getPageTitle(int position) {  return "Tab " + (position + 1); }

        // NOTE: I think you do not really need to override "instantiateItem()", therefore I removed it.
    }
}

关于java - 设备旋转时如何更改不同标记的布局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48359713/

相关文章:

java - 在 Web 浏览器中无法看到 Java Maven Tomcat-plugin Web 应用程序

java - IntelliJ 理念 : Deploy a simple Java servlet (no JSP) to Tomcat 7

Android OpenSL ES 晶振频率

java - 布局问题;重叠按钮

java - 单元测试不在应用服务器中运行时应该如何设置数据源?

java - 隐藏图标但继续运行 Android Studio

java - 调用 Firebase recyclerview 查询的语法

Java/Android Activity 和数据库 close() 问题

android - CustomView 未显示在 ScrollView 内

安卓/ eclipse : This LinearLayout layout or its RelativeLayout parent is possibly useless