Фрагмент перекрывает панель инструментов AppCompat

Я работаю с библиотекой поддержки 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"/>

Note: I found some questions (and answers), but in most cases, the issue was related to AppCompat versions < 19, which is not my case.

Примечание 2: я наследую от Theme.AppCompat.NoActionBar, так как я устанавливаю панель инструментов во время выполнения. Вероятно, я мог бы решить наследование от Theme.AppCompat и избежать использования setSupportActionBar(), но, если возможно, я бы остался с фактической конфигурацией, так как это упрощает управление ActionBar.


person natario    schedule 23.12.2014    source источник


Ответы (5)


Причина в том, что вы помещаете его в макет фрейма, а затем добавляете фрагмент поверх панели инструментов. тебе нужно сделать что-то вроде этого

<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>
person tyczj    schedule 23.12.2014
comment
Легче, чем я думал, спасибо. Мои фрагменты, загруженные в ваш @ id / content_frame, сами по себе будут иметь несколько слоев вложенных макетов. Неужели это так плохо для производительности, как я читаю? - person natario; 23.12.2014
comment
Я делаю это для нескольких своих приложений и не вижу проблем с производительностью - person tyczj; 23.12.2014
comment
Спасибо за ответ, но я предпочитаю использовать атрибут layout_marginTop в content_frame: android: layout_marginTop =? Attr / actionBarSize. Ведь все фрагменты, на которые вы его заменяете, имеют правильную высоту. (Я знаю, что это вопрос 2014 года, но это было мое лучшее решение) - person Geert Berkers; 16.06.2017

Добавьте эту строку в свой FrameLayout

app:layout_behavior="@string/appbar_scrolling_view_behavior"
person Anand Kumar    schedule 24.05.2017
comment
Вы можете использовать эту ссылку для справки https://developer.android.com/reference/android/support/design/widget/AppBarLayout.html. - person Anand Kumar; 07.06.2017

Вы помещаете панель инструментов в тот же 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>

Макет сверху принимает линейный макет и выравнивает макет фрейма (где вы будете раздувать свой framgemt) под панелью инструментов ...

Эти строки

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

говорит, что DrawerLayout должен занять оставшуюся высоту под панелью инструментов.

Однако, если вы хотите отобразить традиционную панель действий / панель инструментов, вам не нужно добавлять панель инструментов в макет xml. Вы просто можете изменить тему занятия на @style/Theme.AppCompat.Light.DarkActionBar

person sockeqwe    schedule 23.12.2014
comment
Еще не пробовал, но мне кажется, что таким образом ящик будет скользить под панелью действий, не закрывая ее, что на самом деле является моим желаемым поведением. Я хочу, чтобы внизу были только фрагменты. - person natario; 23.12.2014
comment
да, таким образом ящик находится под панелью действий ... Если вы хотите отобразить ящик над панелью действий, вы должны сделать это, как описано в @tyczj - person sockeqwe; 23.12.2014
comment
На самом деле это противоречит лучшим методам разработки материалов Google. Drawer должен быть поверх ToolBar - person Mahmoud; 24.02.2018

Это очень просто и просто. Просто следуйте тому, что я пытался сказать ниже.

Вы заменяете любое представление, используя:

**

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

** // Здесь blackFragment - это идентификатор представления FrameLayout. Вы заменяете FrameLayout View на макет фрагмента. Примечание. Это должен быть макет FrameLayout или производные от FrameLayout.

Весь мой код:

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>

** Вы можете увидеть мой экран после того, как я заменил представление FrameLayout на представление фрагмента

введите описание изображения здесь

person Uddhav Gautam    schedule 06.01.2017

У меня два занятия и к ним прикрепляю один фрагмент. В первом действии он отображается справа, а во втором перекрывает панель инструментов. Хотя android:layout_marginTop="?android:attr/actionBarSize" в макете фрагмента может быть решением, я обнаружил ошибку.

Поскольку Kotlin кэширует идентификаторы представлений макетов (вместо 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 никогда не показывает никаких проблем с кешированными идентификаторами во время компиляции или выполнения. Это большая боль.

person CoolMind    schedule 08.02.2019