首页 > 解决方案 > FrameLayout.LayoutParams 不起作用

问题描述

我试图避免活动中出现以下情况(活动的屏幕截图)。当我使用 setMargins 添加边距时,它不起作用。我尝试通过 xml 代码添加边距,最终结果实现了,但它非常耗时,并且不能保证它适用于所有设备。我怎么能在代码中做到这一点?

这是代码。

package com.example.android.tourguide;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.FrameLayout;

public class TouristAttractions extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
private NavigationView mNavigationView;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.menu_item);
    /*
      Finding the Toolbar that is defined in activity_main.xml via the id toolbar.
      Note:The following three lines should be repeated for all the activities that are opened from the MainActivity. Also the toolbar should have an orientation
      which is not zero.
     */
    android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar_for_menu_items);
    /*
       Setting the action bar as the toolbar defined in the above code line
     */
    setSupportActionBar(toolbar);
    /*
      Setting the title text color of the app bar.
     */
    toolbar.setTitleTextColor(ContextCompat.getColor(this, R.color.color_of_text_of_app_bar));
    mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
    /*
       Finding the drawerLayout so that when the user clicks on the menu item of the navigation drawer it should close as we invoke the method closeDrawers()
     */
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {

            if (menuItem.getItemId() == R.id.home_menu) {
                /*
                Opening the home class that is the MainActivity when the Tourist Home menu button is clicked.
                 */
                Intent intentToOpenHomeClass = new Intent(TouristAttractions.this, MainActivity.class);
                startActivity(intentToOpenHomeClass);
            } else if (menuItem.getItemId() == R.id.entertainment_menu) {
                Intent intentToOpenEntertainmentClass = new Intent(TouristAttractions.this, Entertainment.class);
                startActivity(intentToOpenEntertainmentClass);
            } else if (menuItem.getItemId() == R.id.gardens_menu) {
                Intent intentToOpenGardenClass = new Intent(TouristAttractions.this, Garden.class);
                startActivity(intentToOpenGardenClass);
            } else {
                mDrawerLayout.closeDrawers();
            }
            return true;
        }
    });
    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout_for_menu_items);
    ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager_for_menu_items);
    AdapterForFragmentOfTouristAttraction adapterForFragmentOfTouristAttraction = new AdapterForFragmentOfTouristAttraction(this, getSupportFragmentManager());
    viewPager.setAdapter(adapterForFragmentOfTouristAttraction);
    tabLayout.setupWithViewPager(viewPager);
    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) toolbar.getLayoutParams();
    params.setMargins(0, toolbar.getHeight(), 0, 0);
    ActionBar actionbar = getSupportActionBar();
    /*
    actionBar.setDisplayHomeAsUpEnabled(true) will make the icon clickable and add the < at the left of the icon.

     */
    actionbar.setDisplayHomeAsUpEnabled(true);
    /*
    Enabling the menu icon of the navigation.However note we are simply adding the menu icon however clicking on the icon does absolutely nothing.
     */
    actionbar.setHomeAsUpIndicator(R.drawable.baseline_menu_white_24);

}

}

标签: androidandroid-tablayout

解决方案


首先,使用具有垂直方向的 LinearLayout、RelativeLayout 或 ConstraintLayout 将视图置于彼此下方可能是一个更好的主意。在更奇特的用例中,甚至 CoordinatorLayout 可能更适合。

FrameLayouts 主要用于简单地将视图相互叠加,它们之间没有依赖关系。


这就是说,您遇到的问题是因为您toolbar.getHeight()在添加视图后立即使用,这将始终是0. 尝试附加调试器并亲自查看!

原因是 Android 需要一些时间来查看measure -> layout -> draw它的视图,如果您getHeight在添加布局后立即调用,它将不会执行任何这些步骤,从而使值未初始化,在0.

有一些方法可以解决这个问题,但同样,你最好一起使用不同的布局。如果您坚持使用 FrameLayout,最简洁的方法是扩展它并创建自己的,您可以在其中自己测量和布局视图。hacky、难以维护和令人困惑的方法是ViewTreeObserver用来监听变化并对它们做出反应。这很糟糕,因为在触发另一个布局之前,您必须等待完整的布局通过。


不要在这里使用 FrameLayout。


推荐阅读