using System;
using Android.Widget;
using Android.Content;
using Android.Views;
using Android.Util;
using Android.Runtime;
using Android.Views.Animations;
using Android.Graphics.Drawables;
namespace Shared
{
// 存在问题,下拉后不松开手改为上拉,会拦截MotionEventActions.Up事件,导致触发不了刷新
//VerticalRefreshScrolViewLayout 带下拉刷新
///
/// 位置布局
///
public class VerticalRefreshScrolViewLayout : ViewGroup
{
public Action BeginHeaderRefreshingAction;
//public Action beginFooterRefreshingAction;
//private LinearLayout mainLayout;
private MyLoadingHorizontal mHeaderLoadingView;//下拉刷新头部View
//private MyLoadingHorizontal mFooterLoadingView;//上拉加载底部View
///
/// 构造函数
///
public VerticalRefreshScrolViewLayout()
{
viewGroup = new AndroidRefreshScrolView(Application.Activity, null);
(viewGroup as AndroidRefreshScrolView).AlreadyToTopAction += () =>
{
ShowHeaderLoadingView();
};
(viewGroup as AndroidRefreshScrolView).AlreadyToTopUpAction += () =>
{
ShowHeaderAnimationBeginToRefresh();
};
mHeaderLoadingView = new MyLoadingHorizontal(Application.Activity);
HideHeaderLoadingView();
realViewGroup = new AndroidLinearLayout(Application.Activity, this);
(realViewGroup as AndroidLinearLayout).Orientation = Orientation.Vertical;
viewGroup.AddView(realViewGroup);
realViewGroup.AddView(mHeaderLoadingView);
_isCanHeaderRefresh = true;
}
///
/// 视图宽度
///
/// The width.
public override int Width
{
get
{
return base.Width;
}
set
{
base.Width = value;
if (!IsCanRefresh)
{
return;
}
var layoutParameters = realViewGroup.LayoutParameters;
layoutParameters.Width = Width;
realViewGroup.LayoutParameters = layoutParameters;
}
}
///
/// 视图高度
///
/// The height.
public override int Height
{
get
{
return base.Height;
}
set
{
base.Height = value;
if (!IsCanRefresh)
{
return;
}
var layoutParameters = realViewGroup.LayoutParameters;
layoutParameters.Height = Height;
realViewGroup.LayoutParameters = layoutParameters;
}
}
///
/// 是否允许滑动
///
/// true if scroll enabled; otherwise, false.
public bool ScrollEnabled
{
get
{
return (viewGroup as AndroidScrolView).ScrollEnable;
}
set
{
(viewGroup as AndroidScrolView).ScrollEnable = value;
}
}
///
/// 是否正在滑动
///
/// true if decelerating; otherwise, false.
public bool Decelerating
{
get
{
return false;
}
}
//***************************下拉刷新***************************
private void ShowHeaderLoadingView()
{
if (!IsCanHeaderRefresh) return;
if (IsHeaderRefreshing) return;
mHeaderLoadingView.HideProgress();
SetHeaderLoadingViewText(_mHeaderReadyRefreshText);
mHeaderLoadingView.Visibility = ViewStates.Visible;
//(viewGroup as AndroidRefreshScrolView).showHeader();
//showHeader();
}
private void ShowHeaderAnimationBeginToRefresh()
{
if (!IsCanHeaderRefresh) return;
if (!IsHeaderRefreshing)
{
mHeaderLoadingView.ShowProgress();
SetHeaderLoadingViewText(_mHeaderRefreshingText);
if (mHeaderLoadingView.Animation == null)
{
//缩放动画
mHeaderLoadingView.Animation = new ScaleAnimation(
1.0f, 1.2f, 1.0f, 1.2f,
Dimension.RelativeToSelf, 0.5f,
Dimension.RelativeToSelf, 0.5f);
mHeaderLoadingView.Animation.Duration = 300;
}
mHeaderLoadingView.Animation.Reset();
mHeaderLoadingView.Animation.StartNow();
//开始刷新
IsHeaderRefreshing = true;
BeginHeaderRefreshingAction?.Invoke();
}
}
private void SetHeaderLoadingViewText(string mes)
{
mHeaderLoadingView.textView.Text = mes;
}
private void HideHeaderLoadingView()
{
mHeaderLoadingView.Visibility = ViewStates.Gone;
//(viewGroup as AndroidRefreshScrolView).hideHeader();
//hideHeader();
}
string _mHeaderRefreshingText = "正在刷新...";
public string MHeaderRefreshingText
{
get
{
return _mHeaderRefreshingText;
}
set
{
_mHeaderRefreshingText = value;
}
}
string _mHeaderReadyRefreshText = "松开立即刷新";
public string MHeaderReadyRefreshText
{
get
{
return _mHeaderReadyRefreshText;
}
set
{
_mHeaderReadyRefreshText = value;
}
}
///
/// 是否支持下拉刷新
///
bool _isCanHeaderRefresh;
public bool IsCanHeaderRefresh
{
get
{
return _isCanHeaderRefresh;
}
set
{
_isCanHeaderRefresh = value;
}
}
///
/// 是否正在下拉刷新
///
bool _isHeaderRefreshing;
public bool IsHeaderRefreshing {
get
{
return _isHeaderRefreshing;
}
set
{
_isHeaderRefreshing = value;
}
}
/////
///// 启用或者关闭下拉刷新
/////
//public void openHeaderRefresh(bool bOpen)
//{
//}
///
/// 头开始刷新
///
public void BeginHeaderRefreshing()
{
if (!IsCanHeaderRefresh) return;
if (!IsHeaderRefreshing)
{
ShowHeaderLoadingView();
//mHeaderLoadingView.Visibility = ViewStates.Visible;
ShowHeaderAnimationBeginToRefresh();
}
}
///
/// 头结束刷新
///
public void EndHeaderRefreshing()
{
if (!IsCanHeaderRefresh) return;
if (IsHeaderRefreshing)
{
HideHeaderLoadingView();
IsHeaderRefreshing = false;
}
}
//public void showHeader()
//{
// mHeaderLoadingView.SetPadding(0, 0, 0, 0);
//}
//public void hideHeader()
//{
// mHeaderLoadingView.SetPadding(0, 0, 0, -100);
//}
////***************************上拉加载***************************
//string _mFooterRefreshText = "正在加载...";
//public string mFooterRefreshText
//{
// get
// {
// return _mFooterRefreshText;
// }
// set
// {
// _mFooterRefreshText = value;
// }
//}
/////
///// 是否支持 上拉加载
/////
//bool _isCanFooterRefresh;
//public bool IsCanFooterRefresh
//{
// get
// {
// return _isCanFooterRefresh;
// }
// set
// {
// _isCanFooterRefresh = value;
// }
//}
/////
///// 是否正在上拉加载
/////
//bool _isFooterRefreshing;
//public bool IsFooterRefreshing
//{
// get
// {
// return _isFooterRefreshing;
// }
// set
// {
// _isFooterRefreshing = value;
// }
//}
/////
///// 底部 开始上拉加载
/////
//public void beginFooterRefreshing()
//{
// if (!IsCanFooterRefresh) return;
// if (!IsFooterRefreshing)
// {
// mFooterLoadingView.Start(mHeaderRefreshText);
// IsFooterRefreshing = true;
// beginFooterRefreshingAction?.Invoke();
// }
//}
/////
///// 底部 结束上拉加载
/////
//public void endFooterRefreshing()
//{
// if (!IsCanFooterRefresh) return;
// if (IsFooterRefreshing)
// {
// mFooterLoadingView.Hide();
// IsFooterRefreshing = false;
// }
//}
}
///
/// 竖直方向滑动控件
///
class AndroidRefreshScrolView : Android.Widget.ScrollView
{
///
/// 是否允许滑动
///
public bool ScrollEnable = true;
public Action AlreadyToTopAction;
public Action AlreadyToTopUpAction;
public Action AlreadyToBottomAction;
//Scroller mScroller;
//public void showHeader() {
// this.SetPadding(0, 0, 0, 0);
// ////mScroller.
// //mScroller.StartScroll(0, 0, 0, 0, 400);
// //// trigger computeScroll
// //Invalidate();
//}
//public void hideHeader()
//{
// this.SetPadding(0, -50, 0, 0);
// ////mScroller.
// //mScroller.StartScroll(0, 40, 0, -40, 400);
// //// trigger computeScroll
// //Invalidate();
//}
View _view;
///
/// 构造函数
///
/// Context.
/// View.
public AndroidRefreshScrolView(Context context, View view)
: base(context)
{
_view = view;
VerticalScrollBarEnabled = true;
//mScroller = new Scroller(context, new DecelerateInterpolator());
}
bool bAlreadyToTop;
public override bool DispatchTouchEvent(MotionEvent e)
{
//System.Console.WriteLine($"{GetType()} Height->{Height} Width->{Width} DispatchTouchEvent->{e.Action}");
if (e.Action == MotionEventActions.Down)
{
//还原允许拦截事件
RequestDisallowInterceptTouchEvent(false);
}
return base.DispatchTouchEvent(e);
}
float mLastX, mLastY ;
public override bool OnInterceptTouchEvent(MotionEvent ev)
{
//System.Console.WriteLine($"{GetType()} Height->{Height} Width->{Width} OnInterceptTouchEvent->{ev.Action}");
if (!ScrollEnable || disallowIntercept)
{
return false;
}
switch (ev.Action)
{
case MotionEventActions.Down:
mLastX = ev.RawX;
mLastY = ev.RawY;
bAlreadyToTop = false;
System.Console.WriteLine($"MotionEventActions.Down");
Parent?.RequestDisallowInterceptTouchEvent(true);
break;
case MotionEventActions.Up:
Parent?.RequestDisallowInterceptTouchEvent(true);
System.Console.WriteLine($"MotionEventActions.Up");
if (bAlreadyToTop)
{
AlreadyToTopUpAction?.Invoke();
System.Console.WriteLine($"AlreadyToTopUpAction");
}
break;
case MotionEventActions.Move:
var x = ev.RawX;
var y = ev.RawY;
var deltaX = x - mLastX;
var deltaY = y - mLastY;
System.Console.WriteLine($"MotionEventActions.Move");
if (Math.Abs(deltaX) < Math.Abs(deltaY))
{
//向下滑动,如果当前已经滑动到顶,就允许父控件的拦截事件
if (deltaY > 0 && ScrollY == 0)
{
bAlreadyToTop = true;
AlreadyToTopAction?.Invoke();
Parent?.RequestDisallowInterceptTouchEvent(false);
return false;
}
//向上滑动时,如果translateY等于高度时,即表明滑动到底部,可又顶层View控制滑动
var mChildH = 0;
if (0 < ChildCount)
{
mChildH = GetChildAt(ChildCount - 1).Bottom;
}
var translateY = mChildH - ScrollY;
if (deltaY < 0 && translateY == Height)
{
AlreadyToBottomAction?.Invoke();
Parent?.RequestDisallowInterceptTouchEvent(false);
return false;
}
}
else
{
//左右滑动时,允许父控件的拦截
if (4 < Math.Abs(deltaX))
{
Parent?.RequestDisallowInterceptTouchEvent(false);
}
}
break;
}
return base.OnInterceptTouchEvent(ev);
}
///
/// 重写点击事件
///
/// true, if touch event was oned, false otherwise.
/// E.
public override bool OnTouchEvent(MotionEvent e)
{
//System.Console.WriteLine($"{GetType()} Height->{Height} Width->{Width} OnInterceptTouchEvent->{e.Action}");
_view?.TouchEvent(e);
base.OnTouchEvent(e);
//如果返回真父控件就不需要处理了
return true;
}
bool disallowIntercept;
public override void RequestDisallowInterceptTouchEvent(bool disallowIntercept)
{
this.disallowIntercept = disallowIntercept;
//System.Console.WriteLine($"{GetType()} Height->{Height} RequestDisallowInterceptTouchEvent->{disallowIntercept}");
base.RequestDisallowInterceptTouchEvent(disallowIntercept);
Parent?.RequestDisallowInterceptTouchEvent(disallowIntercept);
}
}
class MyLoadingHorizontal : Android.Widget.LinearLayout
{
ProgressBar Progress;
public Android.Widget.TextView textView;
LinearLayout tempLinearLayout;
public void ShowProgress()
{
Progress.Visibility = ViewStates.Visible;
}
public void HideProgress()
{
Progress.Visibility = ViewStates.Gone;
}
public MyLoadingHorizontal(Context context)
: base(context)
{
Progress = new ProgressBar(context);
//SetBackgroundColor (Android.Graphics.Color.Argb (50, 0x32, 0x32, 0x32));
SetGravity(GravityFlags.Center);
tempLinearLayout = new MiddleLinearLayout(context) { Orientation = Orientation.Horizontal };
tempLinearLayout.SetGravity(GravityFlags.CenterHorizontal);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WrapContent, Application.GetRealHeight(30));
lp.Gravity = Android.Views.GravityFlags.Center;
tempLinearLayout.AddView(Progress, lp);
textView = new Android.Widget.TextView(context);
textView.Text = "Loading.....";
textView.Gravity = GravityFlags.Center;
tempLinearLayout.AddView(textView, new Android.Views.ViewGroup.LayoutParams(Android.Views.ViewGroup.LayoutParams.WrapContent, Application.GetRealHeight(40)));
AddView(tempLinearLayout, new Android.Views.ViewGroup.LayoutParams(Android.Views.ViewGroup.LayoutParams.WrapContent, Android.Views.ViewGroup.LayoutParams.WrapContent));
tempLinearLayout.SetPadding(20, 20, 20, 20);
}
uint LoadingHorizontalBackgroundColor;
///
/// 背景颜色
///
/// The color of the background.
public virtual uint LodingBackgroundColor
{
get
{
return LoadingHorizontalBackgroundColor;
}
set
{
LoadingHorizontalBackgroundColor = value;
if (this.GetType() != typeof(ImageView))
{
if (tempLinearLayout.Background == null || tempLinearLayout.Background.GetType() != typeof(GradientDrawable))
{
tempLinearLayout.Background = new Android.Graphics.Drawables.GradientDrawable();
}
var gradientDrawable = (GradientDrawable)tempLinearLayout.Background;
gradientDrawable.SetCornerRadius(DensityUtil.Dip2Px(6));
byte r, g, b, a;
r = (byte)(LoadingHorizontalBackgroundColor / 256 / 256 % 256);
g = (byte)(LoadingHorizontalBackgroundColor / 256 % 256);
b = (byte)(LoadingHorizontalBackgroundColor % 256);
a = (byte)(LoadingHorizontalBackgroundColor / 256 / 256 / 256 % 256);
gradientDrawable.SetColor(Android.Graphics.Color.Argb(a, r, g, b).ToArgb());
}
}
}
///
/// 点击事件
///
/// The touch event.
/// E.
public override bool OnTouchEvent(Android.Views.MotionEvent e)
{
//事件自己处理
return true;
}
}
}