【问题标题】:Fragment overlaps the AppCompat toolbar片段与 AppCompat 工具栏重叠
【发布时间】:2014-12-23 17:06:06
【问题描述】:

我正在使用 v7 支持库并试图在左侧有一个导航抽屉。 正如我在其他地方读到的那样:

  1. DrawerTest.java:存放抽屉的主要活动,我将工具栏加载到其中 使用 setSupportActionBar(),来自自定义 XML 布局,该布局包含 只是Toolbar

  2. toolbar.xml:包含工具栏的 XML 布局;

  3. activity_drawer_listview.xml:一个DrawerLayout XML 资源,用于保存我的片段的容器 (一个 FrameLayout <including> 2 中提到的布局。)和 导航抽屉(一个 ListView);

  4. FragmentTest.java:一些非常简单的片段代码,扩展Fragment

  5. fragment_test_layout.xml:一些非常简单的片段布局,里面只有一个 TextView。

我会在这里粘贴一些代码,无论如何我的问题是片段布局似乎从屏幕顶部开始,而不是从Toolbar 的底部开始。 5. 中的任何文本都将与操作栏上的应用程序标题重叠。我哪里错了?

(1.) DrawerTest.java

    public class DrawerTest extends ActionBarCompat {

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

        DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        Toolbar tb = (Toolbar) findViewById(R.id.toolbar_main2);
        ActionBarDrawerToggle abDrawerToggle = new ActionBarDrawerToggle(
                        this, drawerLayout, tb,
                        R.string.navigation_drawer_open,
                        R.string.navigation_drawer_close )
        {
            // onDrawerClosed() { ... }
            // onDrawerOpened() { ... }
        };
        drawerLayout.setDrawerListener(abDrawerToggle);
        setSupportActionBar(tb);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        abDrawerToggle.syncState();

        //code to load my fragment
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.frame_layout_test, new FragmentTest()).commit();

        }
    }

(3.) activity_drawer_listview.xml

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout"
    android:layout_width="match_parent" android:layout_height="match_parent"
    tools:context="miav.ciotole.DrawerTest">

    <FrameLayout android:id="@+id/frame_layout_test" android:layout_width="match_parent"
        android:layout_height="match_parent" >
    <include layout="@layout/toolbar"/> <!-- What is this line about? -->
    </FrameLayout>

<ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

(4.) FragmentTest.java

    public class FragmentTest extends Fragment {

    public FragmentTest() { }

    @Override
    public View onCreateView(LayoutInflater infl, ViewGroup container, Bundle SavedInstanceState) {
        View rootView = infl.inflate(R.layout.fragment_test_layout, container, false);
        return rootView;
    }
}

(5.) fragment_test_layout.xml

<RelativeLayout 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"
// padding ...
>

<TextView android:id="@+id/section_label" android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"/>

注意:我发现了一些问题(和答案),但在大多数情况下,问题与

注意 2:我从 Theme.AppCompat.NoActionBar 继承,因为我在运行时设置工具栏。可能我可以解决从 Theme.AppCompat 继承的问题并避免使用setSupportActionBar(),但如果可能的话,我会保留实际配置,因为这样更容易控制 ActionBar。

【问题讨论】:

    标签: android android-fragments android-toolbar


    【解决方案1】:

    原因是您将其放置在框架布局中,然后将片段添加到工具栏的顶部。你需要做这样的事情

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
           <LinearLayout
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:orientation="vertical">
    
           <android.support.v7.widget.Toolbar
               android:id="@+id/toolbar"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:minHeight="?attr/actionBarSize"
               android:background="?attr/colorPrimary"
               app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
               app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
    
           <FrameLayout
               android:id="@+id/content_frame"
               android:layout_width="match_parent"
               android:layout_height="match_parent" />
    
           </LinearLayout>
    
           <FrameLayout
           android:id="@+id/left_drawer"
           android:layout_width="325dp"
           android:layout_height="match_parent"
           android:layout_gravity="start"
           android:background="#FFFFFF"/>
    
    </android.support.v4.widget.DrawerLayout>
    

    【讨论】:

    • 比我想象的要容易,谢谢。我在您的@id/content_frame 中加载的片段本身将具有一些嵌套布局层。我读到的性能这么差吗?
    • 我为我的一些应用程序执行此操作,但没有发现性能问题
    • 感谢您的回答,但我更喜欢在 content_frame 中使用属性 layout_marginTop:android:layout_marginTop="?attr/actionBarSize"。在您替换它的所有片段都具有正确的高度之后。 (我知道这是 2014 年的问题,但这是我最好的解决方案)
    【解决方案2】:

    在你的 FrameLayout 中添加这一行

    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    
    【解决方案3】:

    您将工具栏放在同一个 Framelayout 中(id = frame_layout_test)。 FrameLayout 与视图重叠。

    我猜你正在尝试做这样的事情:

    <LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <include layout="@layout/toolbar"/> 
    <!-- I don't know what your Toolbar layout is -->
    
    
        <android.support.v4.widget.DrawerLayout 
            android:layout_width="match_parent" 
            android:layout_height="0dp"
            android:layout_weight="1" 
            tools:context="miav.ciotole.DrawerTest">
    
            <FrameLayout android:id="@+id/frame_layout_test"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
            <ListView
                android:id="@+id/left_drawer"
                android:layout_width="240dp"
                android:layout_height="match_parent"
                android:layout_gravity="start"
                android:choiceMode="singleChoice"
                android:divider="@android:color/transparent"
                android:dividerHeight="0dp" />
    
        </android.support.v4.widget.DrawerLayout>
    </LinearLayout>
    

    上面的布局采用线性布局,并在工具栏下方对齐框架布局(您将在其中膨胀您的框架)...

    这行

    android:layout_height="0dp"
    android:layout_weight="1"
    

    表示 DrawerLayout 应该采用工具栏下方的剩余高度。

    但是,如果您想显示传统的操作栏/工具栏,则不必在 xml 布局中添加工具栏。您只需将活动的主题更改为@style/Theme.AppCompat.Light.DarkActionBar

    【讨论】:

    • 还没试过,但是我感觉这样抽屉会滑到Action Bar下面而不盖住,这其实是我想要的行为。我只希望片段在下面。
    • 是的,这样抽屉就在操作栏的下方......如果你想在操作栏上显示抽屉,那么你应该像@tyczj 描述的那样做
    • 其实这违背了google material design的最佳实践。 Drawer 应该在 ToolBar 之上
    【解决方案4】:

    这非常简单明了。只需按照我在下面尝试说的话。

    您可以使用以下方法替换任何视图:

    **

    getFragmentManager().beginTransaction()
                    .replace(R.id.blankFragment, new SettingsFragment())
                    .commit();
    

    ** //这里,blackFragment是FrameLayout View的id。您将 FrameLayout 视图替换为 Fragment 的布局。 注意:应该是FrameLayout或者FrameLayout的派生Layout。

    我的整个代码是:

    1) SettingsActivity.java

    **

    public class SettingsActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_fragment);
            Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar2);
            mToolbar.setTitle("Settings");
    ////        remove the left margin from the logo
            mToolbar.setPadding(2, 0, 0, 0);//for tab otherwise give space in tab
            mToolbar.setContentInsetsAbsolute(0, 0);
            setSupportActionBar(mToolbar);
            // Display the fragment as the main content
            getFragmentManager().beginTransaction()
                    .replace(R.id.blankFragment, new SettingsFragment())
                    .commit();
        }
    }
    

    **

    2) activity_fragment.xml

    **

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="horizontal">
        <!--scroll|snap-->
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/statusbar"
            android:minHeight="?attr/actionBarSize"
            app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
        <FrameLayout
            android:id="@+id/blankFragment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="?attr/actionBarSize"
            android:layout_gravity="top"
            android:fitsSystemWindows="true"
            android:orientation="horizontal" />
    </FrameLayout>
    

    ** 用 Fragment 的 View 替换 FrameLayout 的 View 后你就可以看到我的 Screen

    【讨论】:

      【解决方案5】:

      我有两个活动,并将一个片段附加到它们。在第一个活动中,它显示在右侧,而在第二个活动中,它与工具栏重叠。虽然片段布局中的android:layout_marginTop="?android:attr/actionBarSize" 可能是一个解决方案,但我发现了一个错误。

      因为 Kotlin 缓存了布局视图的 ids(而不是 findViewById(R.id.some_id),你可以写成 some_id),所以有一个很大的问题。每次复制活动片段时都应该非常小心。因此,每次检查您的导入和附加布局

      我把FirstActivity复制到SecondActivity,把activity_first复制到activity_second,但是忘记改了:

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_first) // Don't forget to change.
      

      同样,在片段中不要忘记:

      override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                                savedInstanceState: Bundle?): View? {
      
          val view = inflater.inflate(R.layout.fragment_yours, container, false)
      

      所以,在我的导入中,我有:

      import kotlinx.android.synthetic.main.activity_second.*
      

      在这种情况下,toolbar 引用了 activity_second,而 activity_first 实际上是附加的。然后片段向上移动 - 就在工具栏的下方。在大多数情况下,Kotlin 在编译或运行时不会显示缓存 id 的任何问题。这是一个很大的痛苦。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-26
        • 2011-02-20
        • 2016-03-03
        • 2018-09-24
        • 1970-01-01
        相关资源
        最近更新 更多