Xamarin Android 使用 ImageView实现帮助引导功能

工厂要求编写一个小系统,最后领导要求在程序界面上增加一个帮助功能,可以显示出每个按钮的作用,我在网上找了很多的资料,不过好像Xamarin平台的资料不多,而且可以第三方例库也没有找到太好用的,就开始自己想,以下就是程序实现:

    class Guider:ImageView 
    {
        Context context;

        Bitmap BackgroudBitmap;
        Bitmap RefreshBitmap;

        private View[] ViewList;
        private int GuiderCount;
        private int CurrentGuider;

        private string[] OPDescription;
        private double TextLineLimit = 20;
        private int DrscriptionTextSize=80;

        private IOnGuiderErrorListener mListener;

        public Guider(Context context, View[] viewList, string[] opDescription,IOnGuiderErrorListener mListener) : base(context)
        {
            this.context = context;
            this.mListener = mListener;

            this.OPDescription = opDescription;
            this.ViewList = viewList;
            this.GuiderCount = viewList.Length-1;
            CurrentGuider = 0;

            this.LayoutParameters = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
            this.SetScaleType(ScaleType.FitXy);
        }

        /// <summary>
        /// 初始化加载视图
        /// </summary>
        /// <returns></returns>
        private bool InitGuiderBitmap()
        {
            try
            {
                if (RefreshBitmap == null) { RefreshBitmap = BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.RefreshGuider); }
                if (BackgroudBitmap == null) {  BackgroudBitmap= BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.Backgroud); }

                return true;
            }
            catch (System.Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 显示Gudier
        /// </summary>
        public bool ShowGudier()
        {
            try
            {
                if (!InitGuiderBitmap()) { return false; }

                if (CurrentGuider < 0 || CurrentGuider > GuiderCount) { return false; }

                Bitmap bitmap = BackgroudBitmap.Copy(Bitmap.Config.Alpha8, true);

                SetImageBitmap(bitmap);
                return true;
            }
            catch (System.Exception ex)
            {
                mListener.ErrorMessage("ShowGuider,"+ex.Message);
                CurrentGuider = -1;
                return false;
            }
        }

        /// <summary>
        /// 重绘事件
        /// </summary>
        /// <param name="canvas"></param>
        protected override void OnDraw(Canvas canvas)
        {
            //base.Draw(canvas);

            //在指定控件周围画出方框
            bool Result= DrawRectBitmap(canvas);
            if (!Result) { return; }

            //在指定控件的周围画出描述信息
            Result=DrawDescriptionBitmap(canvas);
            if (!Result) { return; }

            //在指定位置画出点击继续的提醒
            Result = DrawRefreshBitmap(canvas);
            if (!Result) { return; }

            CurrentGuider += 1;
        }

        /// <summary>
        /// 在指定控件周围画出方框
        /// </summary>
        /// <param name="DestCanvas"></param>
        /// <returns></returns>
        private bool DrawRectBitmap(Canvas DestCanvas)
        {
            try
            {
                if (CurrentGuider<0|| CurrentGuider > GuiderCount) { return false; }

                Bitmap bitmap = BackgroudBitmap.Copy(Bitmap.Config.Alpha8, true);
                Canvas canvas = new Canvas(bitmap);

                Paint RPaint = new Paint();
                RPaint.Color = Color.ParseColor("#FFFFFF");
                RPaint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.SrcOut));

                Rect rect = new Rect();
                int[] position = new int[2];
                ViewList[CurrentGuider].GetLocationInWindow(position);

                rect.Left = position[0] - 20;
                rect.Top = position[1] - 20;
                rect.Right = position[0] + ViewList[0].Width + 20;
                rect.Bottom = position[1]+ ViewList[0].Height  + 20;

                canvas.DrawRect(rect, RPaint);

                Paint paint = new Paint();
                paint.Alpha = 200;
                Rect DestRect = new Rect(0, 0, Width, Height);

                DestCanvas.DrawBitmap(bitmap, null, DestRect, paint);
                canvas.Dispose();
                canvas = null;
                bitmap.Recycle();
                bitmap = null;
                System.GC.Collect();
                return true;
            }
            catch (System.Exception ex)
            {
                mListener.ErrorMessage("DrawRectBitmap," + ex.Message);
                CurrentGuider = -1;
                return false;
            }
        }

        /// <summary>
        /// 在指定控件的周围画出描述信息
        /// </summary>
        /// <param name="DestCanvas"></param>
        /// <returns></returns>
        private bool DrawDescriptionBitmap(Canvas DestCanvas)
        {
            try
            {
                if (CurrentGuider<0|| CurrentGuider > GuiderCount) { return false; }

                Paint TPaint = new Paint
                {
                    Color = Color.White,
                    TextSize = DrscriptionTextSize,
                    TextAlign = Paint.Align.Left
                };

                double TextLines = System.Math.Ceiling(OPDescription[CurrentGuider].Length / TextLineLimit);

                Rect rect = new Rect();
                if (TextLines > 1) { TPaint.GetTextBounds(OPDescription[CurrentGuider].ToCharArray(), 0, 20, rect); }
                else { TPaint.GetTextBounds(OPDescription[CurrentGuider].ToCharArray(), 0, OPDescription[CurrentGuider].Length, rect); }
                
                int[] position = new int[2];
                ViewList[CurrentGuider].GetLocationInWindow(position);

                int Tx = position[0] +100;
                if (Tx + rect.Width() > context.Resources.DisplayMetrics.WidthPixels) { Tx = context.Resources.DisplayMetrics.WidthPixels - rect.Width(); }
                int Ty = position[1] + ViewList[0].Height + 100;
                if (Ty >= context.Resources.DisplayMetrics.HeightPixels)
                {
                    if (TextLines > 1) { Ty = position[1] - 100 - Convert.ToInt32(TextLines * rect.Height()); }
                    else { Ty = position[1] - 100; }
                }
                
                if (TextLines > 1)
                {
                    for(int i=0;i<TextLines;i++)
                    {
                        string txt = "";
                        if (i == ((int)TextLines - 1)) { txt = OPDescription[CurrentGuider].Substring(Convert.ToInt32(i * TextLineLimit)); }
                        else { txt = OPDescription[CurrentGuider].Substring(Convert.ToInt32(i * TextLineLimit), (int)TextLineLimit); }
                        
                        Ty += i * rect.Height();
                        DestCanvas.DrawText(txt, Tx, Ty, TPaint);
                    }
                }
                else { DestCanvas.DrawText(OPDescription[CurrentGuider], Tx, Ty, TPaint); }
                
                TPaint.Dispose();
                TPaint = null;
                return true;
            }
            catch (System.Exception ex)
            {
                mListener.ErrorMessage("DrawDescriptionBitmap,"+ex.Message);
                CurrentGuider = -1;
                return false;
            }
        }

        /// <summary>
        /// 在指定位置画出点击继续的提醒
        /// </summary>
        /// <param name="DestCanvas"></param>
        /// <returns></returns>
        private bool DrawRefreshBitmap(Canvas DestCanvas)
        {
            try
            {
                if (CurrentGuider < 0 || CurrentGuider > GuiderCount) { return false; }

                Paint TPaint = new Paint();
                TPaint.Color = Color.White;
                TPaint.TextSize = 60;
                TPaint.TextAlign = Paint.Align.Left;

                int Tx = context.Resources.DisplayMetrics.WidthPixels - 400;
                int Ty = context.Resources.DisplayMetrics.HeightPixels - 100;

                DestCanvas.DrawBitmap(RefreshBitmap, Tx - 100, Ty - 70, TPaint);
                DestCanvas.DrawText("点击屏幕继续!", Tx, Ty, TPaint);

                TPaint.Dispose();
                TPaint = null;
                return true;
            }
            catch (System.Exception ex)
            {
                mListener.ErrorMessage("DrawRefreshBitmap,"+ex.Message);
                CurrentGuider = -1;
                return false;
            }
        }

        /// <summary>
        /// 销毁进程
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (BackgroudBitmap != null) { BackgroudBitmap.Recycle(); BackgroudBitmap.Dispose(); BackgroudBitmap = null; }
            if (RefreshBitmap != null) { RefreshBitmap.Recycle(); RefreshBitmap.Dispose(); RefreshBitmap = null; }

            base.Dispose(disposing);
        }


        public interface IOnGuiderErrorListener
        {
            void ErrorMessage(string s);
        }

    }

以下为主程序调用:

    [Activity(Label = "App11", MainLauncher = true, Icon = "@mipmap/icon", Theme = "@android:style/Theme.Material.Light.NoActionBar.Fullscreen")]
    public class MainActivity : Activity
    {
        int count = 1;
        Guider guider;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button>(Resource.Id.myButton);
            View v = FindViewById<View>(Resource.Id.button1);
            View v1 = FindViewById<View>(Resource.Id.textView1);
            View v3 = FindViewById<View>(Resource.Id.checkBox5);
            button.Click += delegate {
                View view = FindViewById<View>(Resource.Id.linearLayout1);
                IViewParent viewParent = view.Parent;
                guider = new Guider(this, new View[] { v, v1,v3 }, new string[] { "这是一句很长很长的描述信息,需要测试是否可以自动分行显示啊!", "text2","test3" },new GuiderErrorMessage(this));
                if (viewParent is FrameLayout)
                {
                    FrameLayout frameLayout = (FrameLayout)viewParent;
                                      
                    frameLayout.AddView(guider);
                    guider.ShowGudier();
                    
                    guider.Click += (object sender, System.EventArgs e) =>
                    {
                        if (!guider.ShowGudier()) { frameLayout.RemoveView(guider);guider.Dispose(); }
                    };
                }
            };
        }

        public class GuiderErrorMessage : Guider.IOnGuiderErrorListener
        {
            MainActivity mainActivity;
            public GuiderErrorMessage(MainActivity context)
            {
                this.mainActivity = context;
            }
            public void ErrorMessage(string s)
            {
                //throw new System.NotImplementedException();
                Toast.MakeText(mainActivity, s, ToastLength.Short).Show();
            }
        }

    }

以上为主程序布局图:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="25px"
    android:minHeight="25px"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/frameLayout1">
    <LinearLayout
        android:orientation="vertical"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/linearLayout1">
        <Button
            android:id="@+id/myButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello" />
        <TextView
            android:text="Text"
            android:textSize="40dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textView1" />
        <LinearLayout
            android:orientation="vertical"
            android:minWidth="25px"
            android:minHeight="25px"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/linearLayout2">
            <Button
                android:text="Button"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/button1" />
        </LinearLayout>
        <LinearLayout
            android:orientation="horizontal"
            android:minWidth="25px"
            android:minHeight="25px"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/linearLayout3">
            <CheckBox
                android:text="CheckBox"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:id="@+id/checkBox2" />
            <CheckBox
                android:text="CheckBox"
                android:gravity="left"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/checkBox1" />
            <CheckBox
                android:text="CheckBox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/checkBox3" />
            <CheckBox
                android:text="CheckBox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/checkBox5" />
        </LinearLayout>
    </LinearLayout>
</FrameLayout>

这个帮助引导界面会自动在需要写的VIEW周围生成一个矩形框,在下面会写出功能描述。

不过这个程序还很粗糙,暂时不能在引导界面中动态显示动画,只能显示静态的文字描述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值