获取网格行的绝对宽度

时间:2015-12-21 16:27:34

标签: user-interface xamarin xamarin.forms

我试图模仿iOS UICollectionView的硬编码数据。真的,我只需要在一个由2列3行组成的网格中显示5个方块(最后一个是半个...完整的)

每列的宽度应该是屏幕的一半,这是使用Star(*)完成的。我需要高度总是比宽度小一点。这个想法是有厚厚的矩形。

现在网格在滚动视图中,我不确定它是否相关但我们永远不知道。我这样做,所以较小的手机将始终能够滚动网格,而其他手机可能只有空白。

我一直在试图获取屏幕大小或列宽。我根本无法得到列宽或绝对值的绝对值(总是-1!?)。我可以很容易地得到我的网格项的星值,即1,但我真的只需要帧大小,double值,所以我可以在我的视图的构造函数中调整我的网格并给它绝对值。

问题:

  1. 如何获得列绝对宽度?或者如何将行高设置为与列宽相关的值?

  2. 如果没有可能,我如何获得屏幕宽度,这样我就可以做出可怕的rowheight = screenWdith/2 - padding

  3. 也许有一种非常简单的方法可以使这个过程变得微不足道?

  4. 或者这一切都可能吗?

1 个答案:

答案 0 :(得分:1)

我会回答#2,获得屏幕宽度和高度,你需要一个依赖服务来做你需要的东西:

interface IScreen
    {
        double Width { get; }
        double Height { get; }
        double convertPx(int px);
        string locationName(double latitude, double longitude);
        Task<string> locationNameAsync(double latitude, double longitude);
        string Version { get; }

        void ShowAlertMessage(string aTitle, string aMessage);

    }

机器人:

class Screen_Android : Java.Lang.Object, IScreen
    {
        public Screen_Android() { }

        public double Width
        {
            get
            {
                var ctx = Forms.Context;
                var metrics = ctx.Resources.DisplayMetrics;
                return (ConvertPixelsToDp(metrics.WidthPixels));
            }
        }

        public double Height
        {
            get
            {
                var ctx = Forms.Context;
                var metrics = ctx.Resources.DisplayMetrics;

                return (ConvertPixelsToDp(metrics.HeightPixels));
            }
        }

        private static int ConvertPixelsToDp(float pixelValue)
        {
            var ctx = Forms.Context;
            var dp = (int)((pixelValue) / ctx.Resources.DisplayMetrics.Density);
            return dp;
        }

        public double convertPx(int px)
        {
            var ctx = Forms.Context;

            //var dp = (int)((px) / ctx.Resources.DisplayMetrics.Density);

            //return (int)((dp * ctx.Resources.DisplayMetrics.Density) + 0.5);

            double density = ctx.Resources.DisplayMetrics.Density;
            if (density >= 4.0)
            {
                //"xxxhdpi";
                return px * 4;
            }
            if (density >= 3.0 && density < 4.0)
            {
                //"xxhdpi";
                return px * 3;
            }
            if(density >= 2.0)
            {
                //xhdpi
                return px * 2;
            }
            if(density >= 1.5 && density < 2.0)
            {
                //hdpi
                return px * 1.5;
            }
            if(density >= 1.0 && density < 1.5)
            {
                //mdpi
                return px * 1;
            }
            return px;


            //return (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, px, ctx.Resources.DisplayMetrics);

            //var resources = ctx.Resources;
            //var metrics = resources.DisplayMetrics;
            //int dp = px * ((int)metrics.DensityDpi / 160);
            //return dp;
        }


        public string locationName(double latitude, double longitude)
        {
            //List<Address> addresses;
            Geocoder geocoder = new Geocoder(Forms.Context, Locale.Default);

            try
            {
                var addresses = geocoder.GetFromLocation(latitude, longitude, 10);
                if (addresses.All(item => item == null)) return "";
                string address = addresses[0].GetAddressLine(0);
                string city = addresses[0].GetAddressLine(1);
                string country = addresses[0].GetAddressLine(2);

                return address + " " + city + " " + country;
            }
            catch
            {
                return "";
            }
        }


        public string Version
        {
            get { throw new NotImplementedException(); }
        }


        public void ShowAlertMessage(string aTitle, string aMessage)
        {
            Toast.MakeText(Forms.Context, aMessage, ToastLength.Short).Show();
        }


        public System.Threading.Tasks.Task<string> locationNameAsync(double latitude, double longitude)
        {
            throw new NotImplementedException();
        }

的iOS:

public class Screen_iOS : IScreen
    {
        public double Width
        {
            get
            {
                return UIScreen.MainScreen.Bounds.Width;
            }
        }

        public double Height
        {
            get
            {
                return UIScreen.MainScreen.Bounds.Height;
            }
        }

        public double convertPx(int px)
        {
            throw new NotImplementedException();
        }

        public string locationName(double latitude, double longitude)
        {
            string locationName = "";

            CLLocation c = new CLLocation(Math.Round(latitude, 2), Math.Round(longitude, 2));

            CLGeocoder geocoder = new CLGeocoder();
            geocoder.ReverseGeocodeLocation(c, (placemarks, error) =>
            {
                if ((placemarks != null) && (placemarks.Length > 0))
                    locationName = placemarks[0].Name + placemarks[0].PostalCode + placemarks[0].AdministrativeArea + placemarks[0].Country;

            });

            return locationName;

        }


        public string Version
        {
            get
            {
                NSObject ver = NSBundle.MainBundle.InfoDictionary["CFBundleShortVersionString"];
                return ver.ToString();
            }
            //get { throw new NotImplementedException(); }
        }


        public void ShowAlertMessage(String aTitle, string aMessage)
        {
            UIAlertView error = new UIAlertView(aTitle, aMessage, null, "OK" , null);
            error.Show();
        }


        public async Task<string> locationNameAsync(double latitude, double longitude)
        {

            string locationName = "";

            CLLocation loc = new CLLocation(latitude, longitude);

            CLGeocoder geocoder = new CLGeocoder();

            CLPlacemark[] r = null;
            var task = Task.Factory.StartNew(() =>
            {
                r = geocoder.ReverseGeocodeLocationAsync(loc).Result;
                Console.WriteLine("it ran! {0}", r.Length);
            });

            task.Wait(TimeSpan.FromSeconds(10));

            if ((r != null) && (r.Length > 0))
            locationName = r[0].Name + r[0].PostalCode + r[0].AdministrativeArea + r[0].Country;

            return locationName;
        }
    }