【问题标题】:How to get height of Layout, fiiled with elements programmatically如何获取布局的高度,以编程方式填充元素
【发布时间】:2017-07-11 16:30:24
【问题描述】:

各位程序员大家好。在为 android 创建应用程序时,我遇到了一个问题。我想以编程方式创建 LinearLayout。然后我想以编程方式用不同的元素填充它。之后,我想获取此 LinearLayout 的高度以在将来使用它(例如,用于动画)并将其可见性设置为消失。我在 Activity 的 OnCreate 中执行的所有这些操作,所以如果我尝试获取高度,我得到 0。 任何人都可以帮我解决这个问题。我们将不胜感激所有建议。

更新

GotiasitsAbbas 这里是代码

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    SetContentView(Resource.Layout.TestLayout);
    ScrollView contentScroll = FindViewById<ScrollView>(Resource.Id.contentScroll);
    LinearLayout contentContainer = FindViewById<LinearLayout>(Resource.Id.contentContainer);
    List<DetailsData> dataList = new List<DetailsData>();
    for (int i = 0; i < 3; i++)
    {
        string header = "Header " + " " + i.ToString();
        string title = "Title " + i.ToString();
        string subtitle = "Subtitle";
        string pretext = "Some words in pretext. Some words in pretext. Some words in pretext. Some words in pretext. Some words in pretext. Some words in pretext.Some words in pretext. Some words in pretext.";
        int[] images = { Resource.Drawable.detail_main1, Resource.Drawable.detail_main2, Resource.Drawable.detail_main3, Resource.Drawable.detail_main1,
            Resource.Drawable.detail_main2, Resource.Drawable.detail_main3, Resource.Drawable.detail_main1 };
        string[] features =
        {
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
            "OSome words in featurelist.",
        };
        dataList.Add(new DetailsData(i, header, title, subtitle, pretext, features, images));
    }
    testContainer = new TestContaier(this, dataList, contentContainer, contentScroll, false);
    testContainer.DataBind();
}

class TestContaier
{
    Activity _context;
    public List<DetailsData> _dataSource { get; private set; }
    LinearLayout _mainLayout;
    ScrollView _scrollContainer;
    public TestContaier(Activity context, List<HotelDetailsData> dataSource,  LinearLayout mainLayout, ScrollView scrollContainer)
    {
        _context = context;
        _dataSource = dataSource;
        _mainLayout = mainLayout;
        _firstExpanded = firstExpanded;
        _scrollContainer = scrollContainer;
    }
    public void DataBind()
    {
        bool isFirst = true;
        if (_dataSource != null)
        {
            foreach (var _dataItem in _dataSource)
            {
                TextView header = new TextView(_context)
                {
                    Text = _dataItem._header
                };
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.WrapContent);
                header.SetTextColor(Color.ParseColor(_settings._headerTextColor));
                header.SetBackgroundColor(Color.ParseColor(_settings._headerBackgroundColor));
                header.LayoutParameters = lp;

                View contentView = _context.LayoutInflater.Inflate(Resource.Layout.DetailItem, null);
                ContentViewHolder holder = new ContentViewHolder();

                InitHolder(holder, contentView);

                FillHolder(holder, _dataItem);
                contentView.Visibility = ViewStates.Gone;
                holder.initialize(contentView);
                contentView.Tag = holder;
                header.AssociatedContent = contentView;
                _mainLayout.AddView(header);
                _mainLayout.AddView(contentView);
            }
        }
    }
    void InitHolder(ContentViewHolder holder, View view)
    {
        holder.imageSlider = view.FindViewById<ViewFlipper>(Resource.Id.imageSlider);
        holder.imagesContainer = view.FindViewById<LinearLayout>(Resource.Id.scrollImagesContainer);
        holder.detailTitle = view.FindViewById<TextView>(Resource.Id.detailTitle);
        holder.detailSubtitle = view.FindViewById<TextView>(Resource.Id.detailSubtitle);
        holder.detailPretext = view.FindViewById<TextView>(Resource.Id.detailPreText);
        holder.detailFeatureList = view.FindViewById<LinearLayout>(Resource.Id.detailFeatureList);
        holder.nextSliderButton = view.FindViewById<ImageButton>(Resource.Id.nextSliderButton);
        holder.prevSliderButton = view.FindViewById<ImageButton>(Resource.Id.prevSliderButton);
    }
    void FillHolder(AccordionContentViewHolder holder, HotelDetailsData dataItem)
    {
        /// filling holder with data
    }
}

【问题讨论】:

  • 您是如何以及何时访问高度的?
  • 这是因为当视图完全绘制时,您应该获得视图的高度,例如 onResume() 而不是 onCreate()
  • 致@Abbas 例如在设备屏幕上渲染布局后。但未链接到任何用户操作。它应该“自动”完成
  • To @MaskedMan Nope,在 OnResume() 中它显示为 0,就像在 OnCreate 中一样。
  • @AdeptusMechanicus 你还没有显示 How 即代码。

标签: android layout height


【解决方案1】:

线性布局需要一些时间来测量、传递给其子级并正确获取其高度。所以你必须等到它完成。这是代码

试用并运行:JAVA 代码

    linearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            int height = linearLayout.getMeasuredHeight();

            if( Build.VERSION.SDK_INT > 15){
                linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                linearLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        }
    });

为布局设置监听器,获取高度后,注销GlobalOnLayoutListener

您可以使用linearLayout.getHeight()linearLayout.getMeasuredHeight()。在我的测试中,两者都提供了相同的值

XAMARIN 代码

  ViewTreeObserver vto = _linearLayout.ViewTreeObserver;       
  vto.GlobalLayout += (sender, args) => {      
    var ht = linearLayout.Height;
   };

【讨论】:

  • 致@Ephraim Kigamba。感谢您的建议,但如您所见,我的代码是 C#(我将 Visual Studio 与 Xamarin(不是 XamarinForms)一起使用)。 LinearLayout 没有 getViewTreeObserver() 或属性 ViewTreeObserver 之类的函数。
  • 好的。很抱歉,这段代码可以在 Java 上运行。但是我已经用 XAMARIN CODE 更新了我的代码
【解决方案2】:

您最好的猜测可能是,您可以获取子项目的高度并将其乘以托管视图中的项目数,而不是尝试获取托管 (LinearLayout) 高度。

编辑:这是可能为您提供所需的解决方案。这个函数可以在onCreate()onResume()中调用,只要它可以访问初始化的contentContainer

 public void getHeight(){

    contentContainer.post(new Runnable() {
        @Override
        public void run() {

            int sumHeight=0;
            for(int i=0; i<contentContainer.getChildCount(); i++){
                sumHeight+=contentContainer.getChildAt(i).getHeight();
            }
            Log.d("vidi", "Layout height = " + sumHeight);
        }
    });

正如 Masked Man 很好地指出的那样,如果您的 LinearLayout 中有一些填充或边距,您可以使用 ex. contentContainer.getPaddingBottom 并将其添加到总和中。

.post(Runnable) 的目的只是推迟 Runnable 中的代码,即在 Layout 绘制完成后将这段代码排队运行。

【讨论】:

  • 这是不正确的,因为它可以有填充和边距!
  • ChildViews 的填充和边距将包含在单个高度中。而且我看不出托管视图强制边距有什么意义。
  • 不,这不是最好的。我很伤心 - 我以编程方式创建这些元素,但也不知道它们的高度。
  • 请提供您的 OnCreate 方法,我们或许可以给您更具体的解释。我测试了在我的应用程序中获取子视图的高度,它工作正常。根据我的经验,您的操作方式始终是 0 或全屏高度。
  • @AdeptusMechanicus 您是否设法为您的代码优化了提议的功能?
猜你喜欢
  • 1970-01-01
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-14
相关资源
最近更新 更多