简体   繁体   中英

How to get height of Layout, fiiled with elements programmatically

Hello to all programmers. While I create app for android, I met one problem. I want to create LinearLayout programmatically. Then I want to fill it with different elements programmatically. After that I want to get height of this LinearLayout to use it in future (for animation, for example) and set it's visibility to gone. All this actions I do in OnCreate of Activity, so if I try get height, I got 0. Can anybody help me with this. All suggestions will be appreciated.

UPDATED

For Gotiasits and Abbas here the code

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
    }
}

It takes some time for the linear layout to measure, pass to its children & correctly get its height. So you have to wait until its complete. Here is the code

TRIED IT & WORKING: JAVA CODE

    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);
            }
        }
    });

You set-up a listener for the layout, after getting the height, unregister the GlobalOnLayoutListener

You can either use linearLayout.getHeight() or linearLayout.getMeasuredHeight() . Both provided the same values in my test

XAMARIN CODE

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

Your best guess would probably be that instead of trying to get hosting (LinearLayout) height, you can get the height of your child items and multiply it by the number of items in hosting View.

EDIT : Heres the solution which might get you what you need. This function can be called in both onCreate() and onResume() , as long it has access to initialized 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);
        }
    });

Also as Masked Man nicely pointed out, if you have some padding or margins in your LinearLayout you can get them with ex. contentContainer.getPaddingBottom and add it to the sum.

The purpose of the .post(Runnable) is only to postpone code in Runnable, that is, queue this code to run after Layout has been drawn.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM