上一篇文章我们介绍了如何实现在画板上海书写,其过程相对来说是比较简单的,既然我们实现了画布和画笔,也实现了手写,为了提高可用性,我们增加了对画笔风格的设置功能,这样就可以根据自己的需要选择画笔的颜色、粗细、风格(铅笔、浮雕、水彩等)效果。今天我们就介绍画笔风格的设置功能的实现过程,先看看效果图:


android 实现手写识别 安卓手写设置在哪里_canvas

        

android 实现手写识别 安卓手写设置在哪里_手写签名_02

        

android 实现手写识别 安卓手写设置在哪里_手写签名_03

         

android 实现手写识别 安卓手写设置在哪里_android 实现手写识别_04

一、实现原理:

1、对话款我们用的是popupwindow,不是alertdialog对话框,两者是有区别的:前者是阻塞型,即popupwindow会阻塞主线程,当popupwindow弹出来后,主线程暂停工作,只有popupwindow退出后,主线程才会恢复;alertdialog是非阻塞型,即不会影响到主线程的工作。两者在实现过程中,都是将自定义的布局嵌入到其里面。对于popupwindow对话框的实现,之前的博客【android开发】手机应用管理器的实现之实现popupWindow类对话框(二)已经介绍了,这里就不在介绍了。

2、

android 实现手写识别 安卓手写设置在哪里_canvas_05

  

android 实现手写识别 安卓手写设置在哪里_画笔设置_06

为了更好地显示当前选择画笔的实际效果,我们做了动态预览,这是自定义两个view:ShowLineView和PenCircleView,来完成相应的操作。

3、由于今天要创建的文件比较多,我们来先看一下项目的目录结构图:

android 实现手写识别 安卓手写设置在哪里_android_07


二、实现过程:

首先我们新建一个布局文件pen_set.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout	xmlns:android="http://schemas.android.com/apk/res/android"
    	android:id="@+id/setpenlayout"
	    android:layout_width="wrap_content"
	    android:layout_height="360dp"
	    android:orientation="horizontal"
	    android:background="@drawable/grey_layout">
	<LinearLayout 
	    android:layout_width="wrap_content" 
	    android:layout_height="wrap_content"  android:orientation="vertical" 
	    android:paddingLeft="7dip">
	    <FrameLayout 
	        android:layout_width="195dip"
	        android:layout_height="60dip"
	        android:background="@drawable/white_layout"
    		android:layout_marginRight="5dp"
    		android:layout_marginTop="5dp" >
		<LinearLayout 
		    	android:orientation="horizontal"   android:paddingRight="12dip"
		    	android:layout_width="195dip" android:id="@+id/penShowLayout"
		    	android:layout_height="60dip" >
		</LinearLayout> 
	</FrameLayout>  
	<LinearLayout android:id="@+id/sizeSelectLayoutPen"
		android:layout_width="195dip" android:layout_height="40dip"
		android:orientation="horizontal" 
		android:background="@drawable/darkgrey_layout"
    	android:layout_marginRight="5dp"
    	android:layout_marginTop="5dp"
		android:focusable="false" android:paddingRight="12dip">
		<SeekBar 
		    android:id="@+id/penSizeSeekBar"
		    android:layout_width="140dp"
	        android:layout_marginLeft="10dp"
	        android:max="30"
	        android:layout_height="wrap_content"
	        android:layout_gravity="center_vertical"
	        android:maxHeight="5dp"
	        android:progressDrawable="@drawable/seekbar_bg_img"
	        />
		<LinearLayout
			        android:id="@+id/penSizeShowLayout"
			        android:layout_marginTop="10dp"
			        android:layout_width="40dp"
			        android:layout_height="40dp"
			        android:layout_gravity="center_vertical"
			        android:layout_marginLeft="6dp"
			        android:orientation="horizontal"></LinearLayout>
	</LinearLayout>
	

    <LinearLayout 
	    android:orientation="horizontal"   
	    android:paddingRight="12dip"
	    android:layout_width="195dip" 
	    android:id="@+id/pen_style_seclct"
	    android:layout_height="60dip" 
		android:background="@drawable/deepgrey_layout"
    	android:layout_marginRight="5dp"
    	android:layout_marginTop="5dp">
			<RadioGroup android:id="@+id/penRaidoGroup1"
			android:layout_width="match_parent" android:layout_height="wrap_content"
			android:orientation="horizontal" android:layout_marginTop="8dip">
	    <RadioButton
	    	android:id="@+id/buttonBlurPen" android:layout_weight="1"
			android:layout_width="0dip"  android:button="@null"
			android:layout_height="wrap_content"
			android:background="@drawable/plainpen"
			>
		</RadioButton>
		<RadioButton
	    	android:id="@+id/buttonEmboss" android:layout_weight="1"
			android:layout_width="0dip" android:button="@null"
			android:layout_height="wrap_content"
			 android:background="@drawable/embosspen">
		</RadioButton>
	    <RadioButton
	    	android:id="@+id/buttonPlainPen" android:layout_weight="1"
			android:layout_width="0dip" android:button="@null"
			android:layout_height="wrap_content"
			
			android:background="@drawable/blurpen">
		</RadioButton>
	    <RadioButton
	    	android:id="@+id/buttonSelectBackGroundColor" android:layout_weight="1"
			android:layout_width="0dip" android:button="@null"
			android:layout_height="wrap_content"
			android:background="@drawable/fourpen">
		</RadioButton>
		</RadioGroup>
	</LinearLayout>
	
		<LinearLayout android:layout_width="195dip" 
		    android:background="@drawable/verygrey_layout"
		    android:layout_marginBottom="10dp"
	    	android:layout_marginRight="5dp"
	    	android:layout_marginTop="5dp"
			android:layout_height="75dip" android:id="@+id/LinearLayoutColor"
			android:paddingLeft="7dip" android:orientation="vertical"
			android:paddingRight="10dip">
		
		    
		<LinearLayout android:layout_width="wrap_content" android:layout_height="28dip"
		    android:orientation="horizontal"  android:layout_marginTop="7dip">
		<RadioGroup android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:id="@+id/radioGroupColor"
			android:orientation="horizontal" ></RadioGroup>
		</LinearLayout>
		
		
		<LinearLayout android:layout_width="wrap_content" android:layout_height="28dip"
		    android:orientation="horizontal" >
			<RadioGroup android:layout_width="wrap_content"
			android:layout_height="fill_parent" android:id="@+id/radioGroupColor2"
			android:orientation="horizontal" ></RadioGroup>
		</LinearLayout>
	
		
	</LinearLayout>
	
	</LinearLayout>

	<RelativeLayout
	    android:id="@+id/savedPenLayout"
	    android:layout_width="45dp"
	    android:layout_height="252dp"
	    android:layout_marginBottom="10dp"
	    android:layout_marginRight="5dp"
	    android:layout_marginTop="5dp"
	    android:background="@drawable/verygrey_layout"
	    android:orientation="vertical" >
		    
	</RelativeLayout>
	
	    
	</LinearLayout>



在mudpdfactivity中先初始化控件:

/**
	 * 功能:初始化设置画笔popupwindow视图里面的控件
	 */
	public void initialSetPenBtV(){
		penSetView = getLayoutInflater().inflate(R.layout.pen_set, null);
		setpenlayout = (LinearLayout) penSetView.findViewById(R.id.setpenlayout) ;
		penShowLayout = (LinearLayout) penSetView.findViewById(R.id.penShowLayout) ;
		penSizeSeekBar = (SeekBar) penSetView.findViewById(R.id.penSizeSeekBar) ;
		penSizeShowLayout = (LinearLayout) penSetView.findViewById(R.id.penSizeShowLayout) ;
		colorRadioGroup = (RadioGroup) penSetView.findViewById(R.id.radioGroupColor);
		colorRadioGroup2 = (RadioGroup) penSetView.findViewById(R.id.radioGroupColor2);
		//plainpen = (RadioButton) penSetView.findViewById(R.id.buttonPlainPen);
		penRadioGroupf = (RadioGroup) penSetView.findViewById(R.id.penRaidoGroup1);
		penSizeSeekBar.setOnSeekBarChangeListener(this);
		showLineView = new ShowLineView(this) ;
		penShowLayout.addView(showLineView);
		penCircleView = new PenCircleView(this) ;
		penSizeShowLayout.addView(penCircleView,40,40);
		showLineView.setAttr(6, Color.BLACK, mPenType) ;
		
		initpenRadioGroupf(penSetView);
	}

我们是在长按事件中弹出对话框:

@Override
	public boolean onLongClick(View v) {
		// TODO Auto-generated method stub
		updateLineShow();
		if(penSetPop == null){
			penSetPop = new PopupWindow(penSetView,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);		
			penSetPop.setBackgroundDrawable(getResources().getDrawable(R.drawable.popover_background_left));  
			penSetPop.setFocusable(true);
			penSetPop.setOutsideTouchable(true);
			penSetPop.showAsDropDown(mAddPicButton,0,0);
			initColorViews();
		}else{
			penSetPop.setFocusable(true);
			penSetPop.setOutsideTouchable(true);
			penSetPop.showAsDropDown(mAddPicButton,0,0);
			penSetPop.update();
		}
		return true;//返回false时,点击事件还会响应;返回true,长按事件后点击事件就不响应了
	}

画笔的样式我们共做了四种样式,分别是铅笔、毛笔、签字笔、水彩笔,样式设置主要是通过类BlurMaskFilter和EmbossMaskFilte,通过改变他们的属性变量值来改变画笔书写效果,比如投影值、透明度等,将类BlurMaskFilter和EmbossMaskFilte的实例对象设置好后通过类Paint的方法:setMaskFilter()来传给画笔paint

/**
     * 功能:设置画笔风格
     * @param mPaintType
     * @return
     */
	 private MaskFilter getMaskFilter(int mPaintType){
	    	MaskFilter maskFilter = null;
	    	switch (mPaintType) {
			case PEN_TYPE.PLAIN_PEN://签字笔风格
				maskFilter = null;
				break;
			case PEN_TYPE.BLUR://铅笔模糊风格
				maskFilter = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
				break;
			case PEN_TYPE.EMBOSS://毛笔浮雕风格
				maskFilter = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f); 
				break;
			case PEN_TYPE.TS_PEN://透明水彩风格
				maskFilter = null;
				mPenPaint.setAlpha(50);
				break;
			default:
				maskFilter = null;
				break;
			}
	    	mPenPaint.setMaskFilter(maskFilter);
	    	return maskFilter;
	    }

在对话框中我们四个画笔选项:


/**
	 * 功能:操作设置画笔风格
	 * @param view
	 */
	private void initpenRadioGroupf(View view) {

		plainpen = (RadioButton) view.findViewById(R.id.buttonPlainPen);
		plainpen.setChecked(true);
		penRadioGroupf
				.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
					@Override
					public void onCheckedChanged(RadioGroup group, int checkedId) {				
						if (checkedId == -1) {
							return;
						}
						switch (checkedId) {
						case R.id.buttonBlurPen:
							setToolTyle(PEN_TYPE.BLUR);
							break;
						case R.id.buttonEmboss:
							setToolTyle(PEN_TYPE.EMBOSS);
							break;
						case R.id.buttonPlainPen:
							setToolTyle(PEN_TYPE.PLAIN_PEN);
							break;
						case R.id.buttonSelectBackGroundColor:
							setToolTyle(PEN_TYPE.TS_PEN);
							break;
						default:
							break;
						}
						updateLineShow();
					}
				});
	}
	
	/**
	 * 功能:设置画笔的样式
	 *  */
	private void setToolTyle(int type) {
		//mPaintView.setCurrentPainterType(type);
		mPenType = type;

	}



同时我们设置了十种颜色的选项,通过RadioGroup控件来动态添加选项,每一组五种,分成两组:

/**
	 * 功能:显示颜色选择视图ColorRadioGroup
	 */
	private void initColorRadioGroup() {
		mColorViewList = new ArrayList<ColorView>();
		mColorViewList.add(colorView1);
		mColorViewList.add(colorView2);
		mColorViewList.add(colorView3);
		mColorViewList.add(colorView4);
		mColorViewList.add(colorView5);
		RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(
				COLOR_VIEW_SIZE, COLOR_VIEW_SIZE);
		params.setMargins(1, 2, 6, 6);

		for (ColorView colorView : mColorViewList) {
			colorRadioGroup.addView(colorView, params);
			colorView.setOnCheckedChangeListener(new OnCheckedChangeListener() {
				@Override
				public void onCheckedChanged(CompoundButton buttonView,
						boolean isChecked) {
					for (ColorView colorView : mColorViewList) {
						if (buttonView.equals(colorView)
								&& buttonView.isChecked()) {
							
							colorRadioGroup2.clearCheck();
							penColor = colorView.getColor();
							updateLineShow();
						}
					}
				}
			});
		}
	}
	
	/**
	 * 功能:显示颜色选择视图ColorRadioGroup2
	 */
	private void initColorRadioGroup2() {
		mColorViewList2 = new ArrayList<ColorView>();
		mColorViewList2.add(colorView7);
		mColorViewList2.add(colorView8);
		//mColorViewList.add(colorView9);
		mColorViewList2.add(colorView10);
		mColorViewList2.add(colorView11);
		//mColorViewList.add(colorView12);
		mColorViewList2.add(colorView13);
		RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(
				COLOR_VIEW_SIZE, COLOR_VIEW_SIZE);
		params.setMargins(1, 2, 6, 6);

		for (ColorView colorView2 : mColorViewList2) {
			colorRadioGroup2.addView(colorView2, params);
			colorView2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
				@Override
				public void onCheckedChanged(CompoundButton buttonView,
						boolean isChecked) {
					for (ColorView colorView2 : mColorViewList2) {
						if (buttonView.equals(colorView2)
								&& buttonView.isChecked()) {
							//set the first row unchecked
							colorRadioGroup.clearCheck();
							penColor = colorView2.getColor();
							updateLineShow();
						}
					}
				}
			});
		}
	}

选中后更新两个view:

/**
	 * 功能:更新画笔线条的粗细
	 */
	private void updateLineShow(){
		showLineView.setAttr(penSize, penColor, mPenType) ;
		penCircleView.penAttrChange(penSize, penColor) ;
		//ColorDrawable colorDrawable = new ColorDrawable(mPaintView.getPenColor()) ;
		//pencolor.setBackgroundColor(mPaintView.getPenColor()) ;
	}



进度条来设置画笔的粗细:

@Override
	public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
		// TODO Auto-generated method stub
		penSize = progress;
		updateLineShow();
	}



这样设置对话框基本就完成了,我们设置好,要将相应的数值传递给画笔,我们是通过三个全局变量来保存画笔的颜色、粗细、风格的。

paint.setColor(MuPDFActivity.penColor); //设置画笔的颜色
        paint.setStrokeWidth(MuPDFActivity.penSize);//设置画笔的粗细
        getMaskFilter(MuPDFActivity.mPenType);



当然了我们在实现过程中远比这要复杂,我们创建了几个画笔的接口文件已经封装了几个工具类,我们就不详细说了,可以看看项目的源码。好了,到此今天我们的任务就算结束了,现在读取pdf和书写画板都实现了,剩下就是怎么在pdf上签名了,下一篇我们将继续介绍最关键的一部分-在pdf文件上添加签名。欢迎大家继续关注,由于今天的代码比较多,在文章的最后面我们会将今天的代码分享给大家,项目运行是正常的,如果你在运行中出现问题,请在博客下面留言,大家一起讨论……