【问题标题】:Xamarin Forms ListView for iOS: Always Show ScrollBar适用于 iOS 的 Xamarin 表单 ListView:始终显示 ScrollBar
【发布时间】:2018-01-30 11:43:20
【问题描述】:

我有一个 ObservableCollection<Product> 类型的 ProductList Product 是下面给出的一个类:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Path { get; set; }
}

在我的 Xamarin Forms iOS 应用程序中,我有一个 ListView,其 ItemSourceProductList。当ProductList 中的产品数量使得ListView 的高度不足以显示所有产品时,可以通过滚动ListView 到达其他项目。但是,我希望仅在滚动 ListView 时才显示的 ScrollBar 始终显示。除了ListViev 之外,我是否有可能或者应该尝试其他 UI 以始终显示 ScrollBar。

有一些适用于 Xamarin.Android 的解决方案,但我找不到适用于 iOS 应用的任何有效解决方案。

非常感谢...

【问题讨论】:

标签: c# listview xamarin.ios xamarin.forms


【解决方案1】:

正如@Cole 所说,flashScrollIndicators 只能在短时间内显示指标。

因此,您必须自定义滚动指示器。

创建一个 ListView 的自定义渲染器并添加您的自定义滚动指示器,如下所示:

    public class MyListViewRenderer : ListViewRenderer
    {
        public UIView bar;
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            //Hide the default Scroll Indicator.
            Control.ShowsVerticalScrollIndicator = false;


            //Set Delegate
            CustomScrollDelegate customScrollDelegate = new CustomScrollDelegate();
            Control.Delegate = customScrollDelegate;

            //Create the background view of custom indicator.
            double frameHeight = Control.Frame.Size.Height;
            double frameWidth = Control.Frame.Size.Width;

            double barBackgroundWidth = 6;
            double statusBarHeight = 20;

            UIView barBackgroundView = new UIView();
            CGRect barBVRect = new CGRect(frameWidth - barBackgroundWidth, statusBarHeight, barBackgroundWidth, frameHeight);
            barBackgroundView.Frame = barBVRect;
            barBackgroundView.BackgroundColor = UIColor.Gray;
            barBackgroundView.Layer.CornerRadius = 2;
            barBackgroundView.Layer.MasksToBounds = true;


            //Create the bar of the custom indicator.
            bar = new UIView();
            CGRect barRect = new CGRect(1, 0, 4, 0);
            bar.Frame = barRect;
            bar.BackgroundColor = UIColor.Black;
            bar.Layer.CornerRadius = 2;
            bar.Layer.MasksToBounds = true;

            //Add the views to the superview of the tableview.
            barBackgroundView.AddSubview(bar);
            Control.Superview.AddSubview(barBackgroundView);

            //Transfer the bar view to delegate.
            customScrollDelegate.bar = bar;

        }

        public override void LayoutSubviews()
        {
            base.LayoutSubviews();
            Console.WriteLine("End of loading!!!");
            double contentHeight = Control.ContentSize.Height;
            double frameHeight = Control.Frame.Size.Height;
            double barHeight = frameHeight * frameHeight / contentHeight;


            //Reset the bar height when the table view finishes loading.
            CGRect barRect = new CGRect(bar.Frame.X, bar.Frame.Y, bar.Frame.Width, barHeight);
            bar.Frame = barRect;
        }

    }

实现Scrolled委托,它跟踪scrollView的滚动动作。您可以更新委托中指示器的位置。

    public class CustomScrollDelegate : UIKit.UITableViewDelegate
    {
        public UIView bar;
        double barY;

        public override void Scrolled(UIScrollView scrollView)
        {
            double y = scrollView.ContentOffset.Y;
            double contentHeight = scrollView.ContentSize.Height;
            double frameHeight = scrollView.Frame.Size.Height;

            double barHeight = frameHeight * frameHeight / contentHeight;
            barY = y / (contentHeight - frameHeight) * (frameHeight - barHeight);

            //Cut the bar Height when it over the top.
            if (barY < 0)
            {
                barHeight = barHeight + barY;
                barY = 0;
            }

            //Cut the bar height when it over the bottom.
            if (barY > (frameHeight - barHeight))
            {
               barHeight = barHeight - (barY - (frameHeight - barHeight));
            }

            //Reset the barView rect. Let's move!!!
            CGRect barRect = new CGRect(bar.Frame.X, barY, bar.Frame.Width, barHeight);
            bar.Frame = barRect;

        }

    }

它的工作原理是这样的:

【讨论】:

  • 这正是我所要求的。但是有些地方我无法理解。
  • 1 ) barY 不是滚动条的顶点吗?这是因为当滚动条在顶部时,y 的值为(contentHeight - frameHeight)/2,所以barY 的值为(frameHeight - barHeight)/2。滚动条在顶部不应该是0吗?
  • 2) //当它超过底部时,剪切条的高度。为什么选择(barY &gt; (contentHeight - frameHeight))?我认为当它超过底部时barY &gt; frameHeight - barHeight
  • @Jose,1)。是的,barY 是滚动条的顶部。它应该在顶部为 0。你如何得到 y(contentHeight - frameHeight)/2y 应该是 0,barY 也是 0。
  • @Jose,2)。对不起,这是我的错。我已经更新了我的答案。
猜你喜欢
  • 2012-12-29
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 2017-03-16
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多