using System; using UIKit; using Shared.IO; using CoreGraphics; using Foundation; using CoreAnimation; namespace Shared { /// /// 位置布局 /// public class HorizontalPages : ViewGroup { readonly MyHorizontalPages iosUIScrolView; /// /// 页面变化事件 /// public Action PageChange; /// /// 开始滑动事件 /// public Action StartScrollAction; /// /// 结束滑动事件 /// public Action EndScrollAction ; /// /// 没有更多提示Action,已经是最后一个 /// public Action NoMoreAction; //ImageView LeftImageView = new ImageView() { ImagePath = "RoomIcon/1.jpg" }; //ImageView RightImageView = new ImageView() { ImagePath = "RoomIcon/2.jpg" }; /// /// 构造函数 /// public HorizontalPages() { viewGroup = new UIView(); iosUIScrolView = new MyHorizontalPages(this) { }; iosUIScrolView.Bounces = false; InitMyHorizontalPagesEvent(); realViewGroup = iosUIScrolView; //启动翻页功能 //iosUIScrolView.PagingEnabled = true; iosUIScrolView.ShowsHorizontalScrollIndicator = false; viewGroup.AddSubview(iosUIScrolView); pagePadding = Application.GetRealWidth(50); rowPadding = Application.GetRealWidth(100); mTCBJ = Application.GetRealWidth(50); } ImageView LeftImageView; ImageView RightImageView; /// /// 是否设置了虚假背景View 设置了才显示 /// bool IsSetLeftAndRightImageView = false; /// /// 设置控制最左和最右2边,填充的假背景View,不设置不显示,需要在AddChidren 前调用该方法 /// /// /// public void SetLeftAndRightImageView(ImageView mLeftImageView, ImageView mRightImageView) { if (mLeftImageView == null) return; if (mRightImageView == null) return; //设置之前先清空一次 foreach (var view in iosUIScrolView.Subviews) { view.RemoveFromSuperview(); } LeftImageView = mLeftImageView; iosUIScrolView.AddSubview(LeftImageView.RealView); LeftImageView.Parent = this; LeftImageView.Refresh(); RightImageView = mRightImageView; iosUIScrolView.AddSubview(RightImageView.RealView); RightImageView.Parent = this; RightImageView.Refresh(); IsSetLeftAndRightImageView = true; } bool isNoMore; bool isStart; int mTouchSlop = 20; nfloat beforeXScrollX; nfloat moveX; void InitMyHorizontalPagesEvent() { iosUIScrolView.Scrolled += (s, e) => { //Shared.HDLUtils.WriteLine($"HorizontalPages Scrolled ContentOffsetX:{iosUIScrolView.ContentOffset.X}"); moveX = iosUIScrolView.ContentOffset.X - beforeXScrollX; RefreshPageView(); if (mTouchSlop < Math.Abs(moveX)) { if (!isStart) { //当前索引为,不是第一个或者最后一个,滑动距离大于触发距离并且没执行过则 执行一次StartScrollAction if ((moveX > 0 && PageIndex < ChildrenCount - 1) || (moveX < 0 && PageIndex > 0)) { isStart = true; StartScrollAction?.Invoke(); } } if (!isNoMore && !bSendPageChange) { //当前索引为第一个或者最后一个,滑动距离大于触发距离、没执行过、PageIndex没变化、则执行一次NoMoreAction if ((moveX > 0 && PageIndex == ChildrenCount - 1 && iosUIScrolView.ContentOffset.X > iosUIScrolView.ContentSize.Width - iosUIScrolView.Frame.Width) || (moveX < 0 && PageIndex == 0 && iosUIScrolView.ContentOffset.X < 0)) { isNoMore = true; NoMoreAction?.Invoke(); } } } }; iosUIScrolView.DraggingStarted += (sender, e) => { //Shared.HDLUtils.WriteLine("HorizontalPages DraggingStarted"); SetIsScrolling(true); beforeXScrollX = iosUIScrolView.ContentOffset.X; isStart = false; isNoMore = false; //StartScrollAction?.Invoke(); }; iosUIScrolView.DecelerationStarted += (s, e) => { GetMovePageIndex(); }; iosUIScrolView.DecelerationEnded += (s, e) => { if (!bSendPageChange && (PageIndex == ChildrenCount - 1 || PageIndex == 0 )) { //当前索引为,第一个或者最后一个,并且之前执行过开始Action SendEndScrollAction(); } }; iosUIScrolView.DraggingEnded += (s, e) => { if (!e.Decelerate) { GetMovePageIndex(); } }; iosUIScrolView.ScrollAnimationEnded += (s, e) => { //Shared.HDLUtils.WriteLine("HorizontalPages ScrollAnimationEnded"); SendIfPageChange(); SetIsScrolling(false); }; } private void GetMovePageIndex() { if (mTouchSlop < Math.Abs(moveX)) { if (moveX < 0) { PageIndex -= 1; } else if (moveX > 0) { PageIndex += 1; } } else { PageIndex = PageIndex; } } //两个Page界面之间的距离 int pagePadding; /// /// 界面之间的边距 /// public int JMBJ { get { return pagePadding; } set { pagePadding = value; rowPadding = mTCBJ + pagePadding; RefreshScrollWidth(); ReLocation(); } } //page的与手机屏幕的边距 = 突出宽度 + 两个Page之间的距离 int rowPadding; /// /// 突出宽度 /// int mTCBJ; public int TCBJ { get { return mTCBJ; } set { mTCBJ = value; rowPadding = mTCBJ + pagePadding; RefreshScrollWidth(); ReLocation(); } } int mScrollWidth; int mPageWidth; private void RefreshScrollWidth() { mScrollWidth = (int)this.RealView.Frame.Width - 2 * rowPadding + pagePadding; mPageWidth = (int)this.RealView.Frame.Width - 2 * rowPadding; } /// /// 自动计算刷新所有View的高度,实现缩放效果 /// private void RefreshPageView() { //RefreshView(); //RefreshViewWithTransform3D(); //RefreshViewWithChangeHeight(); RefreshViewWithChangeHeightNew(); //RefreshViewWithChangeHeightSF(); } //********************Transform3D 旋转效果方法********************** //默认25度 nfloat transformAngle = (nfloat)(25 * Math.PI / 180.0); //旋转角度 public int TransformAngle { set { transformAngle = (nfloat)(value * Math.PI / 180.0); } } ///// ///// 旋转效果 ///// //public void RefreshViewWithTransform3D() //{ // if (ChildrenCount <= 0) return; // if (PageIndex > ChildrenCount - 1) // { // PageIndex = ChildrenCount - 1; // } // // - 单位矩阵 // CATransform3D transform = CATransform3D.Identity; // // - 增加透视效果 // transform.m34 = (nfloat)(-1.0 / 500); // var mRotate = transform.Rotate(0, 0f, 1f, 0f); // iosUIScrolView.Subviews[PageIndex].Layer.Transform = mRotate; // //判断PageIndex 前后是否有view,并旋转 // if (PageIndex - 1 >= 0) // { // var mRotate1 = transform.Rotate(transformAngle, 0f, 1f, 0f); // iosUIScrolView.Subviews[PageIndex - 1].Layer.Transform = mRotate1; // } // if (PageIndex <= ChildrenCount - 2) // { // var mRotate2 = transform.Rotate(-1 * transformAngle, 0f, 1f, 0f); // iosUIScrolView.Subviews[PageIndex + 1].Layer.Transform = mRotate2; // } //} /// /// 刷新最大距离值 /// double MaxDistance; private void RefreshViewWithChangeHeight() { if (ChildrenCount <= 0) return; if (PageIndex > ChildrenCount - 1) { PageIndex = ChildrenCount - 1; } MaxDistance = Width - 2 * TCBJ - JMBJ; double centerX = iosUIScrolView.ContentOffset.X + iosUIScrolView.Frame.Width * 0.5; foreach (UIView mSubview in iosUIScrolView.Subviews) { double distance = Math.Abs(mSubview.Center.X - centerX); var HH = 0; if (distance <= 0) { HH = 0; } else if (distance >= MaxDistance) { HH = JMBJ; } else { HH = (int)((distance / MaxDistance) * JMBJ); } var mFrame = mSubview.Frame; mFrame.Height = Height - HH * 2; mFrame.Y = HH; mSubview.Frame = mFrame; //mSubview.MaskView //double distance = Math.Abs(mSubview.Center.X - centerX); //double factor = 0.01; //float scale = (float)(1.0 / (1 + distance * factor)); ////var mFrame = mSubview.Frame; ////mFrame.Height = Height * scale; ////mFrame.Y = (Height - mFrame.Height) / 2; ////mSubview.Frame = mFrame; //var mFrame = mSubview.Frame; //var HH = (int)(MaxChangeHeight - MaxChangeHeight * scale); //mFrame.Height = Height - HH; //mFrame.Y = HH / 2; //mSubview.Frame = mFrame; } } /// /// 同时刷新子view 和ImageView的高度,暂时解决底部圆角失效问题 /// /// /// void RefreshSubviewHeight(View mView, nfloat height) { try { if (mView is ViewGroup) { var tempViewGroup = (ViewGroup)mView; for (int i = 0; i < tempViewGroup.ChildrenCount; i++) { if (tempViewGroup.GetChildren(i) is ViewGroup) { var tempViewGroup2 = (ViewGroup)tempViewGroup.GetChildren(i); for (int j = 0; j < tempViewGroup2.ChildrenCount; j++) { if (tempViewGroup2.GetChildren(j) is ImageView && tempViewGroup2.GetChildren(j).Tag.ToString() == "R") { tempViewGroup2.GetChildren(j).Height = (int)height; break; } } if (tempViewGroup2.Tag.ToString() == "R") { tempViewGroup2.Height = (int)height; break; } } } } } catch { } } /// /// 计算滑动缩放高度的方法 /// private void RefreshViewWithChangeHeightNew() { if (ChildrenCount <= 0) return; if (PageIndex > ChildrenCount - 1) { PageIndex = ChildrenCount - 1; } MaxDistance = Width - 2 * TCBJ - JMBJ; double centerX = iosUIScrolView.ContentOffset.X + iosUIScrolView.Frame.Width * 0.5; for (int i = 0; i < ChildrenCount; i++) { var mSubview = GetChildren(i).RealView; var view = GetChildren(i); double distance = Math.Abs(mSubview.Center.X - centerX); var HH = 0; if (distance <= 0) { HH = 0; } else if (distance >= MaxDistance) { HH = JMBJ; } else { HH = (int)((distance / MaxDistance) * JMBJ); } var mFrame = mSubview.Frame; mFrame.Height = Height - HH * 2; mFrame.Y = HH; mSubview.Frame = mFrame; RefreshSubviewHeight(view, mFrame.Height); } } //private void RefreshViewWithChangeHeightSF() //{ // if (ChildrenCount <= 0) return; // if (PageIndex > ChildrenCount - 1) // { // PageIndex = ChildrenCount - 1; // } // MaxDistance = Width - 2 * TCBJ - JMBJ; // double centerX = iosUIScrolView.ContentOffset.X + iosUIScrolView.Frame.Width * 0.5; // foreach (UIView mSubview in iosUIScrolView.Subviews) // { // double distance = Math.Abs(mSubview.Center.X - centerX); // nfloat HH = 1; // if (distance <= 0) // { // mSubview.Transform = CGAffineTransform.MakeScale(1.0f, 1.0f); // } // else if (distance >= MaxDistance) // { // mSubview.Transform = CGAffineTransform.MakeScale(1.0f, 0.8f); // } // else // { // HH = (nfloat)((1-distance / MaxDistance) * 0.2f) + 0.8f; // mSubview.Transform = CGAffineTransform.MakeScale(1.0f, 0.8f); // } // } //} /// /// 是否允许滑动 /// /// true if scroll enabled; otherwise, false. public bool ScrollEnabled { get { return (iosUIScrolView as MyHorizontalPages).ScrollEnabled; } set { (iosUIScrolView as MyHorizontalPages).ScrollEnabled = value; } } int pageIndex; /// /// 设置或者获取当前的界面索引 /// /// The index of the page. public int PageIndex { get { return pageIndex; } set { if (value < 0 || ChildrenCount <= value) { return; } int beforePageIndex = pageIndex; pageIndex = value; if (!IsCanRefresh) { return; } var viewSize = iosUIScrolView.Frame.Size; RefreshPageView(); var rect = new CGRect(pageIndex * viewSize.Width, 0, viewSize.Width, viewSize.Height); if (pageIndex != 0) { var frame = GetChildren(pageIndex).RealView.Frame; var w = frame.X - rowPadding; rect = new CGRect(w, 0, viewSize.Width, viewSize.Height); //Shared.HDLUtils.WriteLine($"CGRect xx-------{w}"); } //Shared.HDLUtils.WriteLine($"pageIndex xx-------{pageIndex}"); iosUIScrolView.ScrollRectToVisible(rect, true); if (beforePageIndex != pageIndex) { bSendPageChange = true;//发送改变标志 if (!isStart) { isStart = true; StartScrollAction?.Invoke(); } } else { SendEndScrollAction(); } } } /// /// 判断是否需要发送结束滑动事件 /// void SendEndScrollAction() { if (isStart) { isStart = false; EndScrollAction?.Invoke(); } } bool bSendPageChange = false; /// /// 判断是否要发送改变事件 /// private void SendIfPageChange() { if (bSendPageChange) { bSendPageChange = false; PageChange?.Invoke(this, pageIndex); } //判断是否需要发送结束滑动事件 SendEndScrollAction(); } bool isScrolling; /// /// 是否正在滑动 /// public bool ISScrolling { get { return isScrolling; } } private void SetIsScrolling(bool bSctolling) { if (isScrolling == bSctolling) return; Shared.HDLUtils.WriteLine($"HorizontalPages StartScroll: {bSctolling}"); isScrolling = bSctolling; } /// /// 是否正在滑动 /// /// true if decelerating; otherwise, false. public bool Decelerating { get { return iosUIScrolView.Decelerating; } } //public void DelayPageChange() //{ // PageChange?.Invoke(this, pageIndex); // //new System.Threading.Thread(async () => // //{ // // System.Threading.Thread.Sleep(500); // // Application.RunOnMainThread(() => // // { // // PageChange?.Invoke(this, pageIndex); // // }); // //}) // //{ IsBackground = true }.Start(); //} /// /// 增加子控件 /// /// View. public override void AddChidren(View view) { base.AddChidren(view); ReLocation(); } /// /// 重新排位置及设备内容大小 /// public virtual void ReLocation() { try { if (ChildrenCount == 0) { return; } var frame0 = GetChildren(0).RealView.Frame; frame0.X = rowPadding; frame0.Y = 0; frame0.Width = mPageWidth; frame0.Height = iosUIScrolView.Frame.Height; GetChildren(0).RealView.Frame = frame0; for (int i = 1; i < ChildrenCount; i++) { var frame = GetChildren(i).RealView.Frame; frame.Width = mPageWidth; frame.Height = iosUIScrolView.Frame.Height; frame.Y = 0; //frame.X = iosUIScrolView.Subviews[i - 1].Frame.Right + pagePadding; frame.X = rowPadding + (mPageWidth + pagePadding) * i; GetChildren(i).RealView.Frame = frame; } iosUIScrolView.ContentSize = new CoreGraphics.CGSize(GetChildren(ChildrenCount - 1).RealView.Frame.Right + rowPadding, iosUIScrolView.Frame.Height); //iosUIScrolView.ContentSize = new CoreGraphics.CGSize(iosUIScrolView.Subviews[ChildrenCount - 1].Frame.Right + rowPadding, iosUIScrolView.Frame.Height); if (IsSetLeftAndRightImageView) { var leftFrame = iosUIScrolView.Subviews[0].Frame; leftFrame.X = TCBJ - mPageWidth; leftFrame.Y = JMBJ; leftFrame.Width = mPageWidth; leftFrame.Height = Height - JMBJ * 2; iosUIScrolView.Subviews[0].Frame = leftFrame; var rightFrame = iosUIScrolView.Subviews[1].Frame; rightFrame.X = rowPadding + (mPageWidth + pagePadding) * (ChildrenCount); rightFrame.Y = JMBJ; rightFrame.Width = mPageWidth; rightFrame.Height = Height - JMBJ * 2; iosUIScrolView.Subviews[1].Frame = rightFrame; } RefreshPageView(); } catch { } } /// /// 控件宽度 /// /// The width. public override int Width { get { return base.Width; } set { base.Width = value; if (!IsCanRefresh) return; } } /// /// 控件的高度 /// /// The height. public override int Height { get { return base.Height; } set { base.Height = value; if (!IsCanRefresh) return; } } /// /// Bounces /// public bool Bounces { get { return iosUIScrolView.Bounces; } set { iosUIScrolView.Bounces = value; } } /// /// 移除当前控件 /// /// View. internal override void Remove(View view) { base.Remove(view); ReLocation(); if (PageIndex > ChildrenCount - 1) { PageIndex = ChildrenCount - 1; } } /// /// 移除所有的控件 /// public override void RemoveAll() { base.RemoveAll(); ReLocation(); PageIndex = 0; } /// /// 根据索引移除控件 /// /// Index. public override void RemoveAt(int index) { if (viewList.Count - 1 < index || index < 0) { return; } Remove(viewList[index]); } /// /// 垂直方向滚动视图 /// class MyHorizontalPages : UIScrollView { [Weak] HorizontalPages HorizontalPages; public MyHorizontalPages(HorizontalPages HorizontalPages) { this.HorizontalPages = HorizontalPages; } ///// ///// 点击开始 ///// ///// Touches. ///// Evt. //public override void TouchesBegan(NSSet touches, UIEvent evt) //{ // HorizontalPages?.TouchEvent(EventActions.Down, (touches.AnyObject as UITouch).LocationInView(this)); //} //int mTouchSlop = 20; //bool bMove; ///// ///// 移动 ///// ///// Touches. ///// Evt. //public override void TouchesMoved(NSSet touches, UIEvent evt) //{ // HorizontalPages?.TouchEvent(EventActions.Move, (touches.AnyObject as UITouch).LocationInView(this)); //} ///// ///// 点击弹起 ///// ///// Touches. ///// Evt. //public override void TouchesEnded(NSSet touches, UIEvent evt) //{ // HorizontalPages?.TouchEvent(EventActions.Up, (touches.AnyObject as UITouch).LocationInView(this)); //} //public override void TouchesCancelled(NSSet touches, UIEvent evt) //{ // HorizontalPages?.TouchEvent(EventActions.Cancel, (touches.AnyObject as UITouch).LocationInView(this)); //} /// /// 框架默认加了两个UIImageView ,这样可以去掉默认添加 /// /// View. public override void AddSubview(UIView view) { if (view.GetType() == typeof(UIImageView) && view.Tag != int.MinValue) { return; } if (view.ToString().Contains("UIScrollViewScrollIndicator")) { return; } base.AddSubview(view); } } } }