学做婴儿衣服的网站,网页设计与制作教程题,网站提供商,网站开发如何设置视频教程目录 1、背景说明2、实现效果3、代码实现3.1 整体思路3.2 核心绘画类-PaintView.cs3.3 对话框类-WritePadDialog.cs3.4 前端实现类-MainActivity3.5 布局文件3.5.1 write_pad.xml3.5.2 activity_main布局文件 4、知识总结5、代码下载6、参考资料 1、背景说明
在实际使用过程中… 目录 1、背景说明2、实现效果3、代码实现3.1 整体思路3.2 核心绘画类-PaintView.cs3.3 对话框类-WritePadDialog.cs3.4 前端实现类-MainActivity3.5 布局文件3.5.1 write_pad.xml3.5.2 activity_main布局文件 4、知识总结5、代码下载6、参考资料 1、背景说明
在实际使用过程中可能会需要在APP中实现手写板的功能网上比较多的是Android的实现因此找了下资料改了改实现了Xamarin.Android手写板的功能
2、实现效果
实现的效果如下
3、代码实现
3.1 整体思路
在Xamarin.Android中实现绘图主要是两种方式Drawable Resources和Canvas前者可主要进行类似Html的CSS之类的功能后者则实现比较负责的功能本次主要用到了后者-Canvas
整个思路是这样的绘画核心部分通过继承View重写相关方法从而实现笔迹的追踪及记录。对话框主要是实现文件的保存等操作功能前端的界面即MainActivity实现图像的展示具体代码如下
3.2 核心绘画类-PaintView.cs
绘画的核心方法
public class PaintView : View
{private Bitmap mBitmap; //用于存放展示的内容private Path mPath; //路径private Paint mPaint;//关键类private Canvas mCanvas; //画布private int screenWidth, screenHeight;private float currentX, currentY;public PaintView(Context context,int screenWidth,int screenHeight):base(context){this.screenWidth screenWidth;this.screenHeight screenHeight;Initialize();}public PaintView(Context context, IAttributeSet attrs) :base(context, attrs){Initialize();}public PaintView(Context context, IAttributeSet attrs, int defStyle) :base(context, attrs, defStyle){Initialize();}//完成初始化的设置private void Initialize(){mPaint new Paint();mPaint.AntiAlias true;mPaint.Color Color.Black;mPaint.StrokeWidth 5;mPaint.SetStyle(Paint.Style.Stroke);mPath new Path();mBitmapBitmap.CreateBitmap(screenWidth, screenHeight, Bitmap.Config.Argb8888);mCanvas new Canvas(mBitmap);}//重写绘画方法protected override void OnDraw(Canvas canvas){base.OnDraw(canvas);canvas.DrawBitmap(mBitmap, 0, 0, null);canvas.DrawPath(mPath, mPaint);}//重写监听的事件public override bool OnTouchEvent(MotionEvent e){float xe.GetX();float ye.GetY();switch(e.Action){case MotionEventActions.Down:currentX x;currentY y;mPath.MoveTo(currentX, currentY);break;case MotionEventActions.Move: currentX x;currentY y;mPath.QuadTo(currentX, currentY,x,y);break;case MotionEventActions.Up:mCanvas.DrawPath(mPath, mPaint);break;}Invalidate();return true;}// 缩放public static Bitmap resizeImage(Bitmap bitmap, int width, int height){int originWidth bitmap.Width;int originHeight bitmap.Height;float scaleWidth ((float)width) / originWidth;float scaleHeight ((float)height) / originHeight;Matrix matrix new Matrix();matrix.PostScale(scaleWidth, scaleHeight);Bitmap resizedBitmap Bitmap.CreateBitmap(bitmap, 0, 0, originWidth,originHeight, matrix, true);return resizedBitmap;}//清空public void clear(){if (mCanvas ! null){mPath.Reset();mCanvas.DrawColor(Color.Transparent, PorterDuff.Mode.Clear);Invalidate();}}public Bitmap getPaintBitmap(){return resizeImage(mBitmap, 320, 480);}public Path getPath(){return mPath;}}3.3 对话框类-WritePadDialog.cs
public delegate void Handler(object sender);public class WritePadDialog : Dialog
{private Android.Content.Context mContext;private FrameLayout mFrameLayout;private PaintView mPaintView;private Button mBtnOK, mBtnClear, mBtnCancel;public event Handler WriteDialogListener;public WritePadDialog(Android.Content.Context context) : base(context){mContextcontext;}protected override void OnCreate(Bundle savedInstanceState){base.OnCreate(savedInstanceState);RequestWindowFeature(1);//Window.SetFeatureInt(WindowFeatures.NoTitle,5);SetContentView(Resource.Layout.write_pad);mFrameLayout FindViewByIdFrameLayout(Resource.Id.tablet_view);// 获取屏幕尺寸DisplayMetrics mDisplayMetrics new DisplayMetrics();Window.WindowManager.DefaultDisplay.GetMetrics(mDisplayMetrics);int screenWidth mDisplayMetrics.WidthPixels;int screenHeight mDisplayMetrics.HeightPixels;mPaintView new PaintView(mContext, screenWidth, screenHeight);mFrameLayout.AddView(mPaintView);mPaintView.RequestFocus();//保存按钮mBtnOK FindViewByIdButton(Resource.Id.write_pad_ok);mBtnOK.Click MBtnOK_Click;//清空按钮mBtnClear FindViewByIdButton(Resource.Id.write_pad_clear);mBtnClear.Click (o, e) { mPaintView.clear(); };//取消按钮mBtnCancel FindViewByIdButton(Resource.Id.write_pad_cancel);mBtnCancel.Click (o, e) { Cancel(); };}private void MBtnOK_Click(object sender, EventArgs e){if (mPaintView.getPath().IsEmpty){Toast.MakeText(mContext, 请写下你的大名, ToastLength.Short).Show();return;}WriteDialogListener(mPaintView.getPaintBitmap());Dismiss();}
}这儿声明了一个委托delegate主要是想实现通过这个委托将生成的图像传递出去。就是对话框中的eventWriteDialogListener
3.4 前端实现类-MainActivity
protected override void OnCreate(Bundle savedInstanceState){base.OnCreate(savedInstanceState);Xamarin.Essentials.Platform.Init(this, savedInstanceState);SetContentView(Resource.Layout.activity_main);AndroidX.AppCompat.Widget.Toolbar toolbar FindViewByIdAndroidX.AppCompat.Widget.Toolbar(Resource.Id.toolbar);SetSupportActionBar(toolbar);FloatingActionButton fab FindViewByIdFloatingActionButton(Resource.Id.fab);fab.Click FabOnClick;mIVSign FindViewByIdImageView(Resource.Id.signImageView);mTVSign FindViewByIdTextView(Resource.Id.signBtn);mTVSign.Click MTVSign_Click;}private void MTVSign_Click(object sender, EventArgs e){WritePadDialog mWritePadDialog new WritePadDialog(this);mWritePadDialog.WriteDialogListener MWritePadDialog_WriteDialogListener;mWritePadDialog.Show();}private void MWritePadDialog_WriteDialogListener(object sender){mSignBitmap (Bitmap)sender;createSignFile();mIVSign.SetImageBitmap(mSignBitmap);mTVSign.Visibility ViewStates.Gone; }//创建文件
private void createSignFile()
{//ByteArrayOutputStream baos null;MemoryStream baos null;FileOutputStream fos null;String path null;Java.IO.File file null;try{path System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal),DateTime.Now.ToString(yyyyMMddHHmmss) .jpg);file new Java.IO.File(path);fos new FileOutputStream(file);baos new MemoryStream();//如果设置成Bitmap.compress(CompressFormat.JPEG, 100, fos) 图片的背景都是黑色的mSignBitmap.Compress(Bitmap.CompressFormat.Png, 100, baos);byte[] b StreamToBytes(baos);if (b ! null){fos.Write(b);}}catch (Java.IO.IOException e){e.PrintStackTrace();}finally{try{if (fos ! null){fos.Close();}if (baos ! null){baos.Close();}}catch (Java.IO.IOException e){e.PrintStackTrace();}}
}private byte[] StreamToBytes(Stream stream)
{byte[] bytes new byte[stream.Length];stream.Read(bytes, 0, bytes.Length);// 设置当前流的位置为流的开始stream.Seek(0, SeekOrigin.Begin);return bytes;
}这儿有个点在Java中会存在ByteArrayOutputStream 类但是在Xamarin中不存在因此需要进行一个转换。
3.5 布局文件
3.5.1 write_pad.xml
write_pad.xml布局文件如下
?xml version1.0 encodingutf-8?
LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:orientationverticalandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentFrameLayoutandroid:idid/tablet_viewandroid:layout_widthfill_parentandroid:layout_height300dp /FrameLayoutLinearLayoutandroid:layout_widthfill_parentandroid:layout_heightwrap_contentandroid:orientationhorizontalandroid:backgroundandroid:drawable/bottom_barandroid:paddingTop4dp Buttonandroid:idid/write_pad_okandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_weight1android:text确定 /Buttonandroid:idid/write_pad_clearandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_weight1android:text清除 /Buttonandroid:idid/write_pad_cancelandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_weight1android:text取消 //LinearLayout/LinearLayout
3.5.2 activity_main布局文件
?xml version1.0 encodingutf-8?
RelativeLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentapp:layout_behaviorstring/appbar_scrolling_view_behaviortools:showInlayout/activity_mainImageViewandroid:layout_widthmatch_parentandroid:layout_height400dpandroid:idid/signImageView /TextViewandroid:idid/signBtnandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_centerInParenttrueandroid:text请点击我进行签名~ //RelativeLayout
4、知识总结
里面大量的涉及了Canvas的方法可以参考官网的这篇文章Android Graphics and Animation
程序中主要使用了Path类和Canvas具体的知识可以参考资料的第二篇文章非常好
5、代码下载
代码下载
6、参考资料
1、Android实现手写板和涂鸦功能 2、Android知识总结——Path常用方法解析