using System;
using Android.Graphics.Drawables;
using Android.Graphics;
using Android.Views.Animations;
using Android.Views;
using Java.Lang.Ref;
using static Shared.HDLUtils;
using Android.OS;
namespace Shared
{
///
/// 根视图
///
internal class RootView : ViewGroup { }
///
/// 所有类的基类
///
public abstract class View
{
~View()
{
//#if DEBUG
Shared.HDLUtils.WriteLine("=====" + GetType() + " " + Name);
//#endif
if (this is ViewGroup)
{
var viewGroup = this as ViewGroup;
if (viewGroup.realViewGroup != AndroidView)
{
//foreach (var view in viewGroup.viewList)
//{
// view.AndroidView.Dispose();
//}
viewGroup.realViewGroup?.Dispose();
}
}
AndroidView?.Dispose();
}
///
/// 是否需要更新控件
///
/// The is need refresh.
protected bool IsCanRefresh
{
get
{
View tempView = Parent;
while (tempView != null)
{
//根控件,找到根控件后说明已经成功加入了父控件
if (tempView.GetType() == typeof(RootView))
{
return true;
}
tempView = tempView.Parent;
}
return false;
}
}
internal virtual void ClearAllViewEvent()
{
//try
//{
// lock (dimageCached)
// {
// foreach (var key in dimageCached.KeySet())
// {
// var keyString = key.ToString();
// if (keyString.StartsWith($"{GetHashCode()}_", StringComparison.Ordinal))
// {
// dimageCached.Remove(keyString);
// Shared.HDLUtils.WriteLine("=====释放图片" + GetType() + " " + Name);
// (dimageCached.Get(keyString) as Drawable)?.Dispose();
// break;
// }
// }
// }
//}
//catch { }
}
internal virtual void InitAllViewEvent() { }
///
/// 当前对应的AndroidView控件
///
public Android.Views.View AndroidView { get; set; }
///
/// 是否使能
///
/// The enable.
public virtual bool Enable
{
get
{
return AndroidView.Enabled;
}
set
{
AndroidView.Enabled = value;
}
}
int height = LayoutParams.MatchParent;
///
/// 控件的高度
///
/// The height.
public virtual int Height
{
get
{
return AndroidView.LayoutParameters == null ? height : AndroidView.LayoutParameters.Height;
}
set
{
height = value;
if (!IsCanRefresh)
return;
var layoutParameters = AndroidView.LayoutParameters;
if (value == LayoutParams.MatchParent)
{
if (layoutParameters.Height != Parent.Height)
{
layoutParameters.Height = Parent.Height;
AndroidView.LayoutParameters = layoutParameters;
SizeChangeEventHandler?.Invoke(this, new Size(layoutParameters.Width, layoutParameters.Height));
}
}
else
{
if (layoutParameters.Height != value)
{
layoutParameters.Height = value;
AndroidView.LayoutParameters = layoutParameters;
SizeChangeEventHandler?.Invoke(this, new Size(layoutParameters.Width, layoutParameters.Height));
}
}
}
}
int width = LayoutParams.MatchParent;
///
/// 控件宽度
///
/// The width.
public virtual int Width
{
get
{
return AndroidView.LayoutParameters == null ? width : AndroidView.LayoutParameters.Width;
}
set
{
width = value;
if (!IsCanRefresh)
return;
var layoutParameters = AndroidView.LayoutParameters;
if (value == LayoutParams.MatchParent)
{
if (layoutParameters.Width != Parent.Width)
{
layoutParameters.Width = Parent.Width;
AndroidView.LayoutParameters = layoutParameters;
SizeChangeEventHandler?.Invoke(this, new Size(layoutParameters.Width, layoutParameters.Height));
}
}
else
{
if (layoutParameters.Width != value)
{
layoutParameters.Width = value;
AndroidView.LayoutParameters = layoutParameters;
SizeChangeEventHandler?.Invoke(this, new Size(layoutParameters.Width, layoutParameters.Height));
}
}
}
}
///
/// 刷新界面
///
public virtual void Refresh()
{
Width = width;
Height = height;
Gravity = gravity;
Animate = animate;
Radius = tempRadius;
}
///
/// 名称
///
/// The name.
public string Name { get; set; }
int x;
///
/// X轴坐标
///
/// The x.
public int X
{
get
{
return (int)AndroidView.GetX();
}
set
{
x = value;
if (!IsCanRefresh)
{
return;
}
if (Parent is HorizontalPages|| Parent is HorizontalScrolViewLayout)
{
return;
}
else
{
AndroidView.SetX(value);
}
}
}
int y;
///
/// Y轴坐标
///
/// The y.
public int Y
{
get
{
return (int)AndroidView.GetY();
}
set
{
y = value;
if (!IsCanRefresh)
{
return;
}
if (Parent.GetType() == typeof(VerticalScrolViewLayout))
{
return;
}
else
{
AndroidView.SetY(value);
}
}
}
Gravity gravity = Gravity.Frame;
///
/// 控件相对于父控件的对齐方式
///
/// The gravity.
public Gravity Gravity
{
get
{
return gravity;
}
set
{
gravity = value;
if (!IsCanRefresh)
{
return;
}
switch (value)
{
case Gravity.TopLeft:
X = 0;
Y = 0;
break;
case Gravity.TopCenter:
X = (Parent.Width - Width) / 2;
Y = 0;
break;
case Gravity.TopRight:
X = Parent.Width - Width;
Y = 0;
break;
case Gravity.CenterLeft:
X = 0;
Y = (Parent.Height - Height) / 2;
break;
case Gravity.Center:
X = (Parent.Width - Width) / 2;
Y = (Parent.Height - Height) / 2;
break;
case Gravity.CenterRight:
X = Parent.Width - Width;
Y = (Parent.Height - Height) / 2;
break;
case Gravity.BottomLeft:
X = 0;
Y = Parent.Height - Height;
break;
case Gravity.BottomCenter:
X = (Parent.Width - Width) / 2;
Y = Parent.Height - Height;
break;
case Gravity.BottomRight:
X = Parent.Width - Width;
Y = Parent.Height - Height;
break;
case Gravity.CenterVertical:
X = x;
Y = (Parent.Height - Height) / 2;
break;
case Gravity.CenterHorizontal:
X = (Parent.Width - Width) / 2;
Y = y;
break;
case Gravity.Frame:
X = x;
Y = y;
break;
}
}
}
///
/// 左边线位置
///
/// The bottom.
public int Bottom
{
get
{
return Height + Y;
}
}
///
/// 右边线位置
///
/// The right.
public int Right
{
get
{
return Width + X;
}
}
///
/// 当前窗口大小及位置
///
/// The frame.
public virtual Size Size
{
get
{
return new Size(Width, Height);
}
set
{
Width = value.Width;
Height = value.Height;
}
}
///
/// 父容器
///
/// The parent.
public ViewGroup Parent { get; internal set; }
///
/// 处理点击代理
///
/// Sender.
/// E.
internal virtual bool TouchEvent(MotionEvent e)
{
if (!this.Enable)
{
return false;
}
switch (e.Action)
{
case MotionEventActions.Down:
isUp = false;
longClicked = false;
MouseDownEventHandler?.Invoke(this, new MouseEventArgs { X = (int)e.GetX(), Y = (int)e.GetY() });
if (MouseLongEventHandler != null)
{
try
{
if (thread != null && thread.IsAlive)
{
thread.Abort();
}
thread = new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(800);
//Shared.HDLUtils.WriteLine("=====" + isUp);
if (!isUp)
{
longClicked = true;
Application.RunOnMainThread(() =>
{
MouseLongEventHandler(this, new MouseEventArgs { X = (int)e.GetX(), Y = (int)e.GetY() });
});
}
})
{ IsBackground = true };
thread.Start();
}
catch { }
}
break;
case MotionEventActions.Move:
MouseMoveEventHandler?.Invoke(this, new MouseEventArgs { X = (int)e.GetX(), Y = (int)e.GetY() });
break;
case MotionEventActions.Up:
isUp = true;
if (!longClicked && isTouchPointInView(AndroidView, e.RawX, e.RawY))
{
MouseUpEventHandler?.Invoke(this, new MouseEventArgs { X = (int)e.GetX(), Y = (int)e.GetY() });
}
break;
case MotionEventActions.Cancel:
isUp = true;
break;
}
return true;
}
private bool isTouchPointInView(Android.Views.View targetView, float xAxis, float yAxis)
{
if (targetView == null)
{
return false;
}
var location = new int[2];
targetView.GetLocationOnScreen(location);
int left = location[0];
int top = location[1];
int right = left + targetView.Width;
int bottom = top + targetView.Height;
if (yAxis >= top && yAxis <= bottom && xAxis >= left
&& xAxis <= right)
{
return true;
}
return false;
}
bool isUp ;
bool longClicked;
///
/// 点击按下事件
///
public EventHandler MouseDownEventHandler;
///
/// 控件上移动事件
///
public EventHandler MouseMoveEventHandler;
///
/// 点击弹起事件
///
public EventHandler MouseUpEventHandler;
System.Threading.Thread thread;
///
/// 长按点击事件
///
public EventHandler MouseLongEventHandler;
///
/// 大小变化事件
///
public EventHandler SizeChangeEventHandler;
///
/// 将控制移到最前
///
public virtual void BringToFront()
{
AndroidView.BringToFront();
}
Animate animate = Animate.None;
///
/// 动画方式
///
/// The animate.
public Animate Animate
{
get
{
return animate;
}
set
{
animate = value;
if (!IsCanRefresh)
{
return;
}
AndroidView.ClearAnimation();
switch (animate)
{
case Animate.DownToUp:
{
AndroidView.Animation = new TranslateAnimation(
Dimension.RelativeToSelf, 0,
Dimension.RelativeToSelf, 0,
Dimension.RelativeToSelf, 1.0f,
Dimension.RelativeToSelf, 0)
{ Duration = 500 }; // 13828497568
AndroidView.Animation.StartNow();
}
break;
case Animate.UpToDown:
{
AndroidView.Animation = new TranslateAnimation(
Dimension.RelativeToSelf, 0,
Dimension.RelativeToSelf, 0,
Dimension.RelativeToSelf, -1.0f,
Dimension.RelativeToSelf, 0)
{ Duration = 500 };
AndroidView.Animation.StartNow();
}
break;
case Animate.LeftToRight:
{
AndroidView.Animation = new TranslateAnimation(
Dimension.RelativeToSelf, -1.0f,
Dimension.RelativeToSelf, 0,
Dimension.RelativeToSelf, 0f,
Dimension.RelativeToSelf, 0)
{ Duration = 500 };
AndroidView.Animation.StartNow();
}
break;
case Animate.RightToLeft:
{
AndroidView.Animation = new TranslateAnimation(
Dimension.RelativeToSelf, 1.0f,
Dimension.RelativeToSelf, 0,
Dimension.RelativeToSelf, 0f,
Dimension.RelativeToSelf, 0)
{ Duration = 500 };
AndroidView.Animation.StartNow();
}
break;
case Animate.Rotation:
{
AndroidView.Animation = new RotateAnimation(
0,
359,
X + Width / 2.0f,
Y + Height / 2.0f
)
{ Duration = 16000, RepeatCount = -1 };
AndroidView.Animation.StartNow();
}
break;
}
}
}
static Java.Util.HashMap dimageCached = new Java.Util.HashMap();
///
/// 设备控件背景图
///
///
protected bool Background(string filePath)
{
try
{
var drawable = getDrawable(filePath);
if (this.GetType() == typeof(ImageView))
{
(AndroidView as AndroidImageView).SetImageDrawable(drawable);
}
else
{
AndroidView.Background = drawable;
}
if (null != drawable)
{
return true;
}
}
catch { }
return false;
}
protected bool Background(string filePath, Android.Views.View view)
{
AndroidView.Background = getDrawable(filePath);
if (null == view.Background)
{
return false;
}
else
{
return true;
}
}
protected Drawable Bytes2Drawable(byte[] b)
{
var bitmap = Bytes2Bitmap(b);
return bitmap2Drawable(bitmap);
}
protected Drawable bitmap2Drawable(Bitmap bitmap)
{
return new BitmapDrawable(bitmap);
}
// byte[]转换成Bitmap
protected Bitmap Bytes2Bitmap(byte[] b)
{
if (b.Length != 0)
{
return BitmapFactory.DecodeByteArray(b, 0, b.Length);
}
return null;
}
protected Drawable getDrawable(string filePath)
{
try
{
if (filePath == null)
{
return null;
}
var newFilePath = IO.FileUtils.GetImageFilePath(filePath);
if (string.IsNullOrEmpty(newFilePath))
{
AndroidView.Background = null;
return null;
}
var mappingPath = "";// $"{this.GetHashCode()}_";
if (AndroidView.LayoutParameters != null)
{
mappingPath += AndroidView.LayoutParameters.Width + "-" + AndroidView.LayoutParameters.Height + "-";
}
mappingPath += newFilePath;
//lock (dimageCached)
{
if (dimageCached.ContainsKey(mappingPath) && dimageCached.Get(mappingPath) != null)
{
return (Drawable)dimageCached.Get(mappingPath);
}
}
//Shared.HDLUtils.WriteLine(dimageCached.Size() + " ");
var tempBitmapUtiles = AndroidDrawableUtiles.GetAndroidDrawableUtiles(newFilePath, Width, Height);
//加载二次
if (null == tempBitmapUtiles)
{
tempBitmapUtiles = AndroidDrawableUtiles.GetAndroidDrawableUtiles(newFilePath, Width, Height);
}
//两次加载图片都失败,直接返回
if (null == tempBitmapUtiles)
{
AndroidView.Background = null;
return null;
}
//if (mappingPath.Contains("/Room/") || mappingPath.Contains("/Scene/"))
//{
// return tempBitmapUtiles.Drawable;
//}
//lock (dimageCached)
{
try
{
if (dimageCached.ContainsKey(mappingPath))
{
dimageCached.Remove(mappingPath);
dimageCached.Put(mappingPath, tempBitmapUtiles.Drawable);
}
else
{
dimageCached.Put(mappingPath, tempBitmapUtiles.Drawable);
}
return tempBitmapUtiles.Drawable;
}
catch
{
return null;
}
}
}
catch {
return null;
}
}
///
/// 内边距
///
/// The padding.
public virtual Padding Padding
{
get;
set;
}
///
/// 方便开发者开发
///
public object Tag;
System.Collections.Generic.Dictionary tag;
///
/// 增加键值对
///
/// Key.
/// Value.
public void AddTag(string key, object value)
{
if (tag == null)
{
tag = new System.Collections.Generic.Dictionary();
}
tag.Remove(key);
tag.Add(key, value);
}
///
/// 删除指定键值对
///
/// Key.
public void RemoveTag(string key)
{
if (tag == null)
{
return;
}
tag.Remove(key);
}
///
/// 根据键获取值
///
/// The tag by key.
/// Key.
public object GetTagByKey(string key)
{
if (tag == null)
{
return null;
}
object value;
tag.TryGetValue(key, out value);
return value;
}
///
/// 全部删除Tag
///
/// The tag.
public void ClearTag()
{
if (tag != null)
{
tag.Clear();
}
}
///
/// 是否显示
///
/// true if visible; otherwise, false.
public bool Visible
{
get
{
if (AndroidView.Visibility == Android.Views.ViewStates.Visible)
{
return true;
}
else
{
return false;
}
}
set
{
if (value)
{
AndroidView.Visibility = Android.Views.ViewStates.Visible;
}
else
{
AndroidView.Visibility = Android.Views.ViewStates.Invisible;
}
}
}
///
/// 从父视图中移除
///
public virtual void RemoveFromParent()
{
if (Parent == null)
{
return;
}
Parent.Remove(this);
}
///
/// 透明度设置
///
/// The alpha.
public float Alpha
{
get
{
return AndroidView.Alpha;
}
set
{
AndroidView.Alpha = value;
}
}
uint backgroundColor;
///
/// 背景颜色
///
/// The color of the background.
public virtual uint BackgroundColor
{
get
{
return backgroundColor;
}
set
{
backgroundColor = value;
if (this.GetType() != typeof(ImageView))
{
if (AndroidView.Background == null || AndroidView.Background.GetType() != typeof(GradientDrawable))
{
AndroidView.Background = new Android.Graphics.Drawables.GradientDrawable();
}
var gradientDrawable = (GradientDrawable)AndroidView.Background;
//gradientDrawable.SetCornerRadius(DensityUtil.Dip2Px(Radius));
if (IsSetAloneRadius)
{
gradientDrawable.SetCornerRadii(GetCornerRadii());
}
else {
gradientDrawable.SetCornerRadius(Radius);
}
byte r, g, b, a;
r = (byte)(BorderColor / 256 / 256 % 256);
g = (byte)(BorderColor / 256 % 256);
b = (byte)(BorderColor % 256);
a = (byte)(BorderColor / 256 / 256 / 256 % 256);
gradientDrawable.SetStroke((int)BorderWidth, Android.Graphics.Color.Argb(a, r, g, b));
r = (byte)(backgroundColor / 256 / 256 % 256);
g = (byte)(backgroundColor / 256 % 256);
b = (byte)(backgroundColor % 256);
a = (byte)(backgroundColor / 256 / 256 / 256 % 256);
gradientDrawable.SetColor(Android.Graphics.Color.Argb(a, r, g, b).ToArgb());
}
}
}
///
/// 获取指定圆角属性
///
/// The corner.
private float[] GetCornerRadii()
{
float[] mCornerRadius = new float[8];
mCornerRadius[0] = topLeftRadius;
mCornerRadius[1] = topLeftRadius;
mCornerRadius[2] = topRightRadius;
mCornerRadius[3] = topRightRadius;
mCornerRadius[4] = bottomRightRadius;
mCornerRadius[5] = bottomRightRadius;
mCornerRadius[6] = bottomLeftRadius;
mCornerRadius[7] = bottomLeftRadius;
return mCornerRadius;
}
//是否单独设置圆角
public bool IsSetAloneRadius;
//4个圆角分别对应的值
float topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius;
public float mAloneRadius;
public int mRadiusId;
///
/// 指定位置 设置相同的圆角
///
public void SetCornerWithSameRadius(float mRadius, int mSetID)
{
try
{
mAloneRadius = mRadius;
IsSetAloneRadius = true;
mRadiusId = mSetID;
topLeftRadius = (mSetID & 1) == 1 ? mAloneRadius : 0;
topRightRadius = (mSetID >> 1 & 1) == 1 ? mAloneRadius : 0;
bottomLeftRadius = (mSetID >> 2 & 1) == 1 ? mAloneRadius : 0;
bottomRightRadius = (mSetID >> 3 & 1) == 1 ? mAloneRadius : 0;
BackgroundColor = backgroundColor;
}
catch
{
}
}
internal uint radius, tempRadius;
///
/// 圆角大小
///
/// The corner.
public virtual uint Radius
{
get
{
return radius;
}
set
{
IsSetAloneRadius = false;
tempRadius = value;
if (!IsCanRefresh || Radius == value)
{
return;
}
radius = value;
BackgroundColor = backgroundColor;
}
}
uint borderWidth;
///
/// 边框线大小
///
/// The width of the border.
public uint BorderWidth
{
get
{
return borderWidth;
}
set
{
borderWidth = value;
BackgroundColor = backgroundColor;
}
}
uint borderColor = 0xFFCCCCCC;
///
/// 边框颜色
///
/// The color of the border.
public uint BorderColor
{
get
{
return borderColor;
}
set
{
borderColor = value;
BackgroundColor = backgroundColor;
}
}
protected int Dip2Px(float dpValue)
{
float scale = Application.Activity.Resources.DisplayMetrics.Density;
return (int)(dpValue * scale + 0.5f);
}
///
/// 旋转View
///
/// 旋转角度
public void SetRotation(float mRotation)
{
AndroidView.Rotation = mRotation;
}
///
/// 设置阴影效果
///
/// 是否显示阴影
public void SetViewShadow(bool bShow, float mOffsetY = 5.0f)
{
if((int)Build.VERSION.SdkInt >= 21)
{
//AndroidView.TranslationZ = bShow ? Dip2Px(mOffsetY) : 0;
AndroidView.Elevation = bShow ? Dip2Px(mOffsetY) : 0;
}
}
}
public class Size
{
///
/// Initializes a new instance of the class.
///
/// X轴
/// Y轴
/// 宽度
/// 高度
public Size(int width, int height)
{
Width = width;
Height = height;
}
///
/// 宽度
///
public int Width
{
get;
set;
}
///
/// 高度
///
public int Height
{
get;
set;
}
}
///
/// 内边距
///
public class Padding
{
public Padding(int top, int left, int bottom, int right)
{
Top = top;
Left = left;
Bottom = bottom;
Right = right;
}
///
/// 顶部
///
public int Top
{
get;
set;
}
///
/// 左边
///
public int Left
{
get;
set;
}
///
/// 底部
///
public int Bottom
{
get;
set;
}
///
/// 右边
///
public int Right
{
get;
set;
}
}
internal class AndroidDrawableUtiles
{
///
/// 图片对象
///
public Drawable Drawable;
///
/// 图片的高度
///
public int Height;
///
/// 图片的宽度
///
public int Width;
///
/// Initializes a new instance of the class.
///
/// Bitmap drawable.
/// Height.
/// Width.
public AndroidDrawableUtiles(Drawable bitmapDrawable, int height, int width)
{
Drawable = bitmapDrawable;
Height = height;
Width = width;
}
static Bitmap readBitmapFromFileDescriptor(string filePath, int width, int height)
{
try
{
var fis = new Java.IO.FileInputStream(filePath);
var options = new BitmapFactory.Options();
options.InJustDecodeBounds = true;
BitmapFactory.DecodeFileDescriptor(fis.FD, null, options);
float srcWidth = options.OutWidth;
float srcHeight = options.OutHeight;
int inSampleSize = 1;
if (srcHeight > height || srcWidth > width)
{
if (srcWidth > srcHeight)
{
inSampleSize = (int)Math.Round(srcHeight / height);
}
else
{
inSampleSize = (int)Math.Round(srcWidth / width);
}
}
options.InJustDecodeBounds = false;
options.InSampleSize = inSampleSize;
return (Bitmap)new SoftReference(BitmapFactory.DecodeFileDescriptor(fis.FD, null, options)).Get();
}
catch (Exception ex)
{
}
return null;
}
public static AndroidDrawableUtiles GetAndroidDrawableUtiles(string filePath, int width, int height)
{
var bitmap = readBitmapFromFileDescriptor(filePath, width, height);
//BitmapFactory.Options options = new BitmapFactory.Options();
//options.InJustDecodeBounds = true;
//BitmapFactory.DecodeFile(filePath, options);
////图片不存在,直接返回
//if (0 == options.OutWidth || 0 == options.OutHeight)
//{
// Shared.HDLUtils.WriteLine(filePath+"找不到");
// return null;
//}
//options.InSampleSize = getFitInSampleSize(width, height, options);
//options.InJustDecodeBounds = false;
//var bitmap = BitmapFactory.DecodeFile(filePath, options);
//var drawable = new BitmapDrawable(bitmap);
//if (drawable.Bitmap != bitmap && !bitmap.IsRecycled)
//{
// Shared.HDLUtils.WriteLine("释放图片资源:" + filePath);
// bitmap.Recycle();
//}
//var drawable = new BitmapDrawable(bitmap);
if (bitmap == null)
{
return new AndroidDrawableUtiles(null, bitmap.Width, bitmap.Height);
}
else
{
return new AndroidDrawableUtiles((BitmapDrawable)new SoftReference(new BitmapDrawable(bitmap)).Get(), bitmap.Width, bitmap.Height);
}
}
static int getFitInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options)
{
int inSampleSize = 1;
if (options.OutWidth > reqWidth || options.OutHeight > reqHeight)
{
int widthRatio = (int)Math.Round(options.OutWidth * 1.0 / reqWidth);
int heightRatio = (int)Math.Round(options.OutHeight * 1.0 / reqHeight);
inSampleSize = Math.Min(widthRatio, heightRatio);
}
return inSampleSize;
}
}
///
/// 点击时基本参数
///
public class MouseEventArgs : EventArgs
{
///
/// X坐标
///
public float X;
///
/// Y坐标
///
public float Y;
}
public class AndroidView
{
//是否是活动状态
public static bool IsLive(Android.Views.View view)
{
return view.Enabled && view.Visibility == ViewStates.Visible && 0 < view.Alpha;
}
}
}