赞
踩
拍照
添加画板
录音
书写转文字
添加图片
1,主页面
2,功能
贴代码:
1,AndroidManifest.xml文件(添加权限)
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.llw.notes"> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.AppCompat.Light"> <activity android:name=".ShowRecord" android:exported="true" > </activity> <activity android:name=".ShowPicture" android:exported="true"> </activity> <activity android:name=".HandWriteActivity" android:exported="true" /> <activity android:name=".ActivityRecord" android:exported="true" /> <activity android:name=".PaintActivity" android:exported="true" /> <activity android:name=".AddActivity" android:exported="true" > </activity> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
2,Activity文件
ActivityRecord
package com.llw.notes; import android.content.Intent; import android.graphics.drawable.AnimationDrawable; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class ActivityRecord extends AppCompatActivity { private Button btn_record; private int isRecording = 0; private int isPlaying = 0; //语音保存路径 private String FilePath = null; private Timer mTimer; private ImageView iv_microphone; private TextView tv_recordTime; private ImageView iv_record_wave_left,iv_record_wave_right; private AnimationDrawable ad_left,ad_right; //语音操作对象 private MediaPlayer mPlayer = null; private MediaRecorder mRecorder = null; Button btn_save; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_record); //设置为全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ActionBar actionBar=getSupportActionBar(); actionBar.hide(); btn_save = findViewById(R.id.bt_save); btn_save.setOnClickListener(new ClickEvent()); Button btn_back = (Button)findViewById(R.id.bt_back); btn_back.setOnClickListener(new ClickEvent()); btn_record = (Button)findViewById(R.id.btn_record); btn_record.setOnClickListener(new ClickEvent()); iv_microphone = (ImageView)findViewById(R.id.iv_microphone); iv_microphone.setOnClickListener(new ClickEvent()); iv_record_wave_left = (ImageView)findViewById(R.id.iv_record_wave_left); iv_record_wave_right = (ImageView)findViewById(R.id.iv_record_wave_right); // ad_left = (AnimationDrawable)iv_record_wave_left.getBackground(); // ad_left = (AnimationDrawable)iv_record_wave_left.getBackground(); // 通过逐帧动画的资源文件获得AnimationDrawable示例 iv_record_wave_left.setImageResource(R.drawable.record_wave_left); iv_record_wave_right.setImageResource(R.drawable.record_wave_right); ad_left=((AnimationDrawable) iv_record_wave_left.getDrawable()); ad_right=((AnimationDrawable) iv_record_wave_right.getDrawable()); tv_recordTime = (TextView)findViewById(R.id.tv_recordTime); } final Handler handler = new Handler(){ public void handleMessage(Message msg) { switch(msg.what){ case 1 : String time[] = tv_recordTime.getText().toString().split(":"); int hour = Integer.parseInt(time[0]); int minute = Integer.parseInt(time[1]); int second = Integer.parseInt(time[2]); if(second < 59){ second++; } else if(second == 59 && minute < 59){ minute++; second = 0; } if(second == 59 && minute == 59 && hour < 98){ hour++; minute = 0; second = 0; } time[0] = hour + ""; time[1] = minute + ""; time[2] = second + ""; //调整格式显示到屏幕上 if(second < 10) time[2] = "0" + second; if(minute < 10) time[1] = "0" + minute; if(hour < 10) time[0] = "0" + hour; //显示在TextView中 tv_recordTime.setText(time[0]+":"+time[1]+":"+time[2]); break; } } }; class ClickEvent implements View.OnClickListener { @Override public void onClick(View v) { switch(v.getId()){ //点击的是开始录音按钮 case R.id.btn_record : //开始录音 if(isRecording == 0){ //每一次调用录音,可以录音多次,至多满意为至,最后只将最后一次的录音文件保存,其他的删除 if(FilePath != null){ File oldFile = new File(FilePath); oldFile.delete(); } //获得系统当前时间,并以该时间作为文件名 SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmss"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String str = formatter.format(curDate); str = str + "record.amr"; File dir = new File("/sdcard/notes/"); File file = new File("/sdcard/notes/",str); if (!dir.exists()) { dir.mkdir(); } else{ if(file.exists()){ file.delete(); } } FilePath = dir.getPath() +"/"+ str; //计时器 mTimer = new Timer(); //将麦克图标设置成不可点击, iv_microphone.setClickable(false); //将显示的时间设置为00:00:00 tv_recordTime.setText("00:00:00"); //将按钮换成停止录音 isRecording = 1; btn_record.setBackgroundResource(R.drawable.tabbar_record_stop); mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setOutputFile(FilePath); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { mRecorder.prepare(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mRecorder.start(); mTimer.schedule(new TimerTask() { @Override public void run() { Message message = new Message(); message.what = 1; handler.sendMessage(message); } },1000, 1000); //播放动画 ad_left.start(); ad_right.start(); } //停止录音 else{ //将按钮换成开始录音 isRecording = 0; btn_record.setBackgroundResource(R.drawable.tabbar_record_start); mRecorder.stop(); mTimer.cancel(); mTimer = null; mRecorder.release(); mRecorder = null; //将麦克图标设置成可点击, iv_microphone.setClickable(true); //停止动画 ad_left.stop(); ad_right.stop(); Toast.makeText(ActivityRecord.this, "单击麦克图标试听,再次点击结束试听", Toast.LENGTH_LONG).show(); } break; //如果单击的是麦克图标,则可以是进入试听模式,再次点击,停止播放 case R.id.iv_microphone : if(FilePath == null) Toast.makeText(ActivityRecord.this, "没有录音广播可以播放,请先录音", Toast.LENGTH_LONG).show(); else{ //试听 if(isPlaying == 0){ isPlaying = 1; mPlayer = new MediaPlayer(); tv_recordTime.setText("00:00:00"); mTimer = new Timer(); mPlayer.setOnCompletionListener(new MediaCompletion()); try { mPlayer.setDataSource(FilePath); mPlayer.prepare(); mPlayer.start(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mTimer.schedule(new TimerTask() { @Override public void run() { Message message = new Message(); message.what = 1; handler.sendMessage(message); } }, 1000,1000); //播放动画 ad_left.start(); ad_right.start(); } //结束试听 else{ isPlaying = 0; mPlayer.stop(); mPlayer.release(); mPlayer = null; mTimer.cancel(); mTimer = null; //停止动画 ad_left.stop(); ad_right.stop(); } } break; //点击确定按钮 case R.id.bt_save : //将最终的录音文件的路径返回 Intent intent = getIntent(); Bundle b = new Bundle(); b.putString("audio", FilePath); intent.putExtras(b); setResult(RESULT_OK, intent); ActivityRecord.this.finish(); break; case R.id.bt_back : //返回前将录音的文件删除 if(FilePath != null){ File oldFile = new File(FilePath); oldFile.delete(); } ActivityRecord.this.finish(); break; } } } class MediaCompletion implements MediaPlayer.OnCompletionListener { @Override public void onCompletion(MediaPlayer mp) { mTimer.cancel(); mTimer = null; isPlaying = 0; //停止动画 ad_left.stop(); ad_right.stop(); Toast.makeText(ActivityRecord.this, "播放完毕", Toast.LENGTH_LONG).show(); tv_recordTime.setText("00:00:00"); } } }
AddActivity
package com.llw.notes; import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.text.Editable; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.text.style.ImageSpan; import android.view.View; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.Button; import android.widget.GridView; import android.widget.SimpleAdapter; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class AddActivity extends AppCompatActivity { private GridView bottomMenu; private LineEditText et_Notes; private Button bt_back; private Button bt_save; private SQLiteDatabase db; private DatabaseOperation dop; Intent intent; String editModel = null; int item_Id; InputMethodManager imm; //底部按钮 private int[] bottomItems = { R.drawable.tabbar_handwrite, R.drawable.tabbar_paint, R.drawable.tabbar_microphone, R.drawable.tabbar_photo, R.drawable.tabbar_camera, R.drawable.tabbar_appendix }; //记录editText中的图片,用于单击时判断单击的是那一个图片 private List<Map<String,String>> imgList = new ArrayList<Map<String,String>>(); //配置底部菜单 private void initBottomMenu(){ ArrayList<Map<String,Object>> menus = new ArrayList<Map<String,Object>>(); for(int i = 0;i < bottomItems.length;i++){ Map<String,Object> item = new HashMap<String,Object>(); item.put("image",bottomItems[i]); menus.add(item); } bottomMenu.setNumColumns(bottomItems.length); bottomMenu.setSelector(R.drawable.bottom_item); SimpleAdapter mAdapter = new SimpleAdapter(AddActivity.this, menus,R.layout.item_button, new String[]{"image"}, new int[]{R.id.item_image}); bottomMenu.setAdapter(mAdapter); } private TextView tv_title; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add); //设置为全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ActionBar actionBar=getSupportActionBar(); actionBar.hide(); et_Notes = (LineEditText)findViewById(R.id.et_note); et_Notes.setOnClickListener(new TextClickEvent()); bottomMenu = (GridView)findViewById(R.id.bottomMenu); //配置菜单 initBottomMenu(); bottomMenu.setOnItemClickListener(new MenuClickEvent()); bt_back = (Button)findViewById(R.id.bt_back); bt_back.setOnClickListener(new ClickEvent()); bt_save = (Button)findViewById(R.id.bt_save); bt_save.setOnClickListener(new ClickEvent()); //默认关闭软键盘,可以通过失去焦点设置 //et_Notes.setFocusable(false); imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(et_Notes.getWindowToken(),0); dop = new DatabaseOperation(this,db); intent = getIntent(); editModel = intent.getStringExtra("editModel"); item_Id = intent.getIntExtra("noteId", 0); tv_title = (TextView)findViewById(R.id.tv_title); loadData(); } //为EidtText设置监听器 class TextClickEvent implements View.OnClickListener { @Override public void onClick(View v) { Spanned s = et_Notes.getText(); ImageSpan[] imageSpans; imageSpans = s.getSpans(0, s.length(), ImageSpan.class); int selectionStart = et_Notes.getSelectionStart(); for(ImageSpan span : imageSpans){ int start = s.getSpanStart(span); int end = s.getSpanEnd(span); //找到图片 if(selectionStart >= start && selectionStart < end){ //Bitmap bitmap = ((BitmapDrawable)span.getDrawable()).getBitmap(); //查找当前单击的图片是哪一个图片 //System.out.println(start+"-----------"+end); String path = null; for(int i = 0;i < imgList.size();i++){ Map map = imgList.get(i); //找到了 if(map.get("location").equals(start+"-"+end)){ path = imgList.get(i).get("path"); break; } } //接着判断当前图片是否是录音,如果为录音,则跳转到试听录音的Activity,如果不是,则跳转到查看图片的界面 //录音,则跳转到试听录音的Activity if(path.substring(path.length()-3, path.length()).equals("amr")){ Intent intent = new Intent(AddActivity.this,ShowRecord.class); intent.putExtra("audioPath", path); startActivity(intent); } //图片,则跳转到查看图片的界面 else{ //有两种方法,查看图片,第一种就是直接调用系统的图库查看图片,第二种是自定义Activity //调用系统图库查看图片 /*Intent intent = new Intent(Intent.ACTION_VIEW); File file = new File(path); Uri uri = Uri.fromFile(file); intent.setDataAndType(uri, "image/*");*/ //使用自定义Activity Intent intent = new Intent(AddActivity.this,ShowPicture.class); intent.putExtra("imgPath", path); startActivity(intent); } } else //如果单击的是空白出或文字,则获得焦点,即打开软键盘 imm.showSoftInput(et_Notes, 0); } } } //加载数据 private void loadData(){ //如果是新增记事模式,则将editText清空 if(editModel.equals("newAdd")){ et_Notes.setText(""); } //如果编辑的是已存在的记事,则将数据库的保存的数据取出,并显示在EditText中 else if(editModel.equals("update")){ tv_title.setText("编辑记事"); dop.create_db(); Cursor cursor = dop.query_db(item_Id); cursor.moveToFirst(); //取出数据库中相应的字段内容 @SuppressLint("Range") String context = cursor.getString(cursor.getColumnIndex("context")); //定义正则表达式,用于匹配路径 Pattern p=Pattern.compile("/([^\\.]*)\\.\\w{3}"); Matcher m=p.matcher(context); int startIndex = 0; while(m.find()){ //取出路径前的文字 if(m.start() > 0){ et_Notes.append(context.substring(startIndex, m.start())); } SpannableString ss = new SpannableString(m.group().toString()); //取出路径 String path = m.group().toString(); //取出路径的后缀 String type = path.substring(path.length() - 3, path.length()); Bitmap bm = null; Bitmap rbm = null; //判断附件的类型,如果是录音文件,则从资源文件中加载图片 if(type.equals("amr")){ bm = BitmapFactory.decodeResource(getResources(), R.drawable.record_icon); //缩放图片 rbm = resize(bm,200); } else{ //取出图片 bm = BitmapFactory.decodeFile(m.group()); //缩放图片 rbm = resize(bm,480); } //为图片添加边框效果 rbm = getBitmapHuaSeBianKuang(rbm); System.out.println(rbm.getWidth()+"-------"+rbm.getHeight()); ImageSpan span = new ImageSpan(this, rbm); ss.setSpan(span,0, m.end() - m.start(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); et_Notes.append(ss); startIndex = m.end(); //用List记录该录音的位置及所在路径,用于单击事件 Map<String,String> map = new HashMap<String,String>(); map.put("location", m.start()+"-"+m.end()); map.put("path", path); imgList.add(map); } //将最后一个图片之后的文字添加在TextView中 et_Notes.append(context.substring(startIndex,context.length())); dop.close_db(); } } //等比例缩放图片 private Bitmap resize(Bitmap bitmap,int S){ int imgWidth = bitmap.getWidth(); int imgHeight = bitmap.getHeight(); double partion = imgWidth*1.0/imgHeight; double sqrtLength = Math.sqrt(partion*partion + 1); //新的缩略图大小 double newImgW = S*(partion / sqrtLength); double newImgH = S*(1 / sqrtLength); float scaleW = (float) (newImgW/imgWidth); float scaleH = (float) (newImgH/imgHeight); Matrix mx = new Matrix();//坐标 //对原图片进行缩放 mx.postScale(scaleW, scaleH); bitmap = Bitmap.createBitmap(bitmap, 0, 0, imgWidth, imgHeight, mx, true); return bitmap; } //给图片加边框,并返回边框后的图片 public Bitmap getBitmapHuaSeBianKuang(Bitmap bitmap) { float frameSize = 0.2f; Matrix matrix = new Matrix(); // 用来做底图 Bitmap bitmapbg = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); // 设置底图为画布 Canvas canvas = new Canvas(bitmapbg); canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); float scale_x = (bitmap.getWidth() - 2 * frameSize - 2) * 1f / (bitmap.getWidth()); float scale_y = (bitmap.getHeight() - 2 * frameSize - 2) * 1f / (bitmap.getHeight()); matrix.reset(); matrix.postScale(scale_x, scale_y); // 对相片大小处理(减去边框的大小) bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); Paint paint = new Paint(); paint.setColor(Color.WHITE); paint.setStrokeWidth(1); paint.setStyle(Paint.Style.FILL); // 绘制底图边框 canvas.drawRect( new Rect(0, 0, bitmapbg.getWidth(), bitmapbg.getHeight()), paint); // 绘制灰色边框 paint.setColor(Color.BLUE); canvas.drawRect( new Rect((int) (frameSize), (int) (frameSize), bitmapbg .getWidth() - (int) (frameSize), bitmapbg.getHeight() - (int) (frameSize)), paint); canvas.drawBitmap(bitmap, frameSize + 1, frameSize + 1, paint); return bitmapbg; } //设置按钮监听器 class ClickEvent implements View.OnClickListener { @Override public void onClick(View v) { switch(v.getId()){ case R.id.bt_back : //当前Activity结束,则返回上一个Activity AddActivity.this.finish(); break; //将记事添加到数据库中 case R.id.bt_save : //取得EditText中的内容 String context = et_Notes.getText().toString(); if(context.isEmpty()){ Toast.makeText(AddActivity.this, "记事为空!", Toast.LENGTH_LONG).show(); } else{ //取得当前时间 SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String time = formatter.format(curDate); //截取EditText中的前一部分作为标题,用于显示在主页列表中 String title = (String) getTitle(context); //打开数据库 dop.create_db(); //判断是更新还是新增记事 if(editModel.equals("newAdd")){ //将记事插入到数据库中 dop.insert_db(title,context,time); } //如果是编辑则更新记事即可 else if(editModel.equals("update")){ dop.update_db(title,context,time,item_Id); } dop.close_db(); Intent intent=new Intent(AddActivity.this,MainActivity.class); startActivity(intent); //结束当前activity AddActivity.this.finish(); } break; } } } //截取EditText中的前一部分作为标题,用于显示在主页列表中 private String getTitle(String context){ //定义正则表达式,用于匹配路径 Pattern p=Pattern.compile("/([^\\.]*)\\.\\w{3}"); Matcher m=p.matcher(context); StringBuffer strBuff = new StringBuffer(); String title = ""; int startIndex = 0; while(m.find()){ //取出路径前的文字 if(m.start() > 0){ strBuff.append(context.substring(startIndex, m.start())); } //取出路径 String path = m.group().toString(); //取出路径的后缀 String type = path.substring(path.length() - 3, path.length()); //判断附件的类型 if(type.equals("amr")){ strBuff.append("[录音]"); } else{ strBuff.append("[图片]"); } startIndex = m.end(); //只取出前15个字作为标题 if(strBuff.length() > 15){ //统一将回车,等特殊字符换成空格 title = strBuff.toString().replaceAll("\r|\n|\t", " "); return title; } } strBuff.append(context.substring(startIndex, context.length())); //统一将回车,等特殊字符换成空格 title = strBuff.toString().replaceAll("\r|\n|\t", " "); return title; } //设置菜单项监听器 class MenuClickEvent implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent; switch(position){ //手写 case 0: intent = new Intent(AddActivity.this,HandWriteActivity.class); startActivityForResult(intent, 5); break; //绘图 case 1: intent = new Intent(AddActivity.this,PaintActivity.class); startActivityForResult(intent, 3); break; //语音 case 2: intent = new Intent(AddActivity.this,ActivityRecord.class); startActivityForResult(intent, 4); break; //照片 case 3: intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*"); startActivityForResult(intent, 1); break; //拍照 case 4 : //调用系统拍照界面 intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); //区分选择相片 startActivityForResult(intent, 2); //附件 case 5 : break; } } } //将图片等比例缩放到合适的大小并添加在EditText中 void InsertBitmap(Bitmap bitmap,int S,String imgPath){ bitmap = resize(bitmap,S); //添加边框效果 bitmap = getBitmapHuaSeBianKuang(bitmap); //bitmap = addBigFrame(bitmap,R.drawable.line_age); final ImageSpan imageSpan = new ImageSpan(this,bitmap); SpannableString spannableString = new SpannableString(imgPath); spannableString.setSpan(imageSpan, 0, spannableString.length(), SpannableString.SPAN_MARK_MARK); //光标移到下一行 //et_Notes.append("\n"); Editable editable = et_Notes.getEditableText(); int selectionIndex = et_Notes.getSelectionStart(); spannableString.getSpans(0, spannableString.length(), ImageSpan.class); //将图片添加进EditText中 editable.insert(selectionIndex, spannableString); //添加图片后自动空出两行 et_Notes.append("\n"); //用List记录该录音的位置及所在路径,用于单击事件 Map<String,String> map = new HashMap<String,String>(); map.put("location", selectionIndex+"-"+(selectionIndex+spannableString.length())); map.put("path", imgPath); imgList.add(map); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode == RESULT_OK){ //取得数据 Uri uri = data.getData(); ContentResolver cr = AddActivity.this.getContentResolver(); Bitmap bitmap = null; Bundle extras = null; //如果是选择照片 if(requestCode == 1){ // 这里开始的第二部分,获取图片的路径: String[] proj = {MediaStore.Images.Media.DATA}; Cursor cursor = managedQuery(uri, proj, null, null, null); //按我个人理解 这个是获得用户选择的图片的索引值 int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); //最后根据索引值获取图片路径 String path = cursor.getString(column_index); System.out.println("pppppp:"+path); try { //将对象存入Bitmap中 bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } //插入图片 InsertBitmap(bitmap,480,path); } //如果选择的是拍照 else if(requestCode == 2){ System.out.println("-----fjwefowefwef");; try { if(uri != null) //这个方法是根据Uri获取Bitmap图片的静态方法 bitmap = MediaStore.Images.Media.getBitmap(cr, uri); //这里是有些拍照后的图片是直接存放到Bundle中的所以我们可以从这里面获取Bitmap图片 else{ extras = data.getExtras(); bitmap = extras.getParcelable("data"); } //将拍的照片存入指定的文件夹下 //获得系统当前时间,并以该时间作为文件名 SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmss"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String str = formatter.format(curDate); String paintPath = ""; str = str + "paint.png"; File dir = new File("/sdcard/notes/"); File file = new File("/sdcard/notes/",str); if (!dir.exists()) { dir.mkdir(); } else{ if(file.exists()){ file.delete(); } } FileOutputStream fos = new FileOutputStream(file); // 将 bitmap 压缩成其他格式的图片数据 bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); String path = "/sdcard/notes/" + str; //插入图片 System.out.println("tttttttttt:"+path); InsertBitmap(bitmap,480,path); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //返回的是绘图后的结果 else if(requestCode == 3){ extras = data.getExtras(); String path = extras.getString("paintPath"); //通过路径取出图片,放入bitmap中 bitmap = BitmapFactory.decodeFile(path); //插入绘图文件 InsertBitmap(bitmap,480,path); } //返回的是录音文件 else if(requestCode == 4){ extras = data.getExtras(); String audioPath = extras.getString("audio"); bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.record_microphone_icon); //插入录音图标 InsertBitmap(bitmap,80,audioPath); } //返回的是手写文件 else if(requestCode == 5){ extras = data.getExtras(); String path = extras.getString("handwritePath"); //通过路径取出图片,放入bitmap中 bitmap = BitmapFactory.decodeFile(path); //插入绘图文件 InsertBitmap(bitmap,680,path); } } } }
DatabaseOperation
package com.llw.notes; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.widget.Toast; public class DatabaseOperation { private SQLiteDatabase db; private Context context; public DatabaseOperation(Context context,SQLiteDatabase db) { this.db = db; this.context = context; } //数据库的打开或创建 public void create_db(){ //创建或打开数据库 db = SQLiteDatabase.openOrCreateDatabase(context.getFilesDir().toString()+"/mynotes.db3", null); db.execSQL("DROP TABLE IF EXISTS studentScore"); if(db == null){ Toast.makeText(context,"数据库创建不成功",Toast.LENGTH_LONG).show(); } //Toast.makeText(context,"数据库创建成功",Toast.LENGTH_LONG).show(); //创建表 db.execSQL("create table if not exists notes(_id integer primary key autoincrement," + "title text," + "context text," + "time varchar(20))"); } public void insert_db(String title,String text,String time){ if(text.isEmpty()){ Toast.makeText(context, "各字段不能为空", Toast.LENGTH_LONG).show(); } else{ db.execSQL("insert into notes(title,context,time) values('"+ title+"','"+ text+ "','"+time+"');"); //Toast.makeText(context, "插入成功", Toast.LENGTH_LONG).show(); } } public void update_db(String title,String text,String time,int item_ID){ if( text.isEmpty()){ Toast.makeText(context, "各字段不能为空", Toast.LENGTH_LONG).show(); } else{ //String sql = "update main set class1='" + class1 + "',class2='" + class2 + "',class3='" + class4 + "',class4='" + class4 + "'where days='" + days + "';"; db.execSQL("update notes set context='"+text+ "',title='"+title+"',time='"+time+"'where _id='" + item_ID+"'"); //Toast.makeText(context, "修改成功", Toast.LENGTH_LONG).show(); } } public Cursor query_db(){ Cursor cursor = db.rawQuery("select * from notes",null); return cursor; } public Cursor query_db(int item_ID){ Cursor cursor = db.rawQuery("select * from notes where _id='"+item_ID+"';",null); return cursor; } public void delete_db(int item_ID){ db.execSQL("delete from notes where _id='" + item_ID+"'"); //Toast.makeText(context, "删除成功", Toast.LENGTH_LONG).show(); } //关闭数据库 public void close_db(){ db.close(); } }
GetCutBitampLocation
package com.llw.notes; public class GetCutBitmapLocation { private float cutLeft = 0; private float cutTop = 0; private float cutRight = 0; private float cutBottom = 0; public void init(float x,float y){ cutLeft = x; cutRight = x; cutTop = y; cutBottom = y; } //更新手写字的左右上下的位置 public void setCutLeftAndRight(float x,float y){ cutLeft = (x < cutLeft ? x : cutLeft); cutRight = (x > cutRight ? x : cutRight); cutTop = (y < cutTop ? y : cutTop); cutBottom = (y > cutBottom ? y : cutBottom); } //返回手写字的切割位置 public float getCutLeft(){ return cutLeft; } public float getCutTop(){ return cutTop; } public float getCutRight(){ return cutRight; } public float getCutBottom(){ return cutBottom; } }
HandWriteActivity
package com.llw.notes; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.Editable; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ImageSpan; import android.view.View; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.Button; import android.widget.GridView; import android.widget.LinearLayout; import android.widget.SimpleAdapter; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map; public class HandWriteActivity extends AppCompatActivity { private LinearLayout paintLayout; private GridView paint_bottomMenu; private LineEditText et_handwrite; private TouchView touchView; private ArrayList<CharSequence> deleteChar = new ArrayList<CharSequence>(); //菜单资源 private int[] paintItems = { R.drawable.paint_pencil, R.drawable.paint_icon_color, R.drawable.paint_icon_back, R.drawable.paint_icon_forward, R.drawable.paint_icon_delete }; private Button btn_save; private Button btn_back; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hand_write); //设置为全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ActionBar actionBar=getSupportActionBar(); actionBar.hide(); paint_bottomMenu = (GridView)findViewById(R.id.paintBottomMenu); paint_bottomMenu.setOnItemClickListener(new MenuClickEvent()); et_handwrite = (LineEditText)findViewById(R.id.et_handwrite); InitPaintMenu(); touchView = (TouchView)findViewById(R.id.touch_view); touchView.setHandler(handler); btn_save = (Button)findViewById(R.id.bt_save); btn_back = (Button)findViewById(R.id.bt_back); btn_save.setOnClickListener(new ClickEvent()); btn_back.setOnClickListener(new ClickEvent()); } class ClickEvent implements View.OnClickListener { @Override public void onClick(View v) { if(v == btn_save){ //得到调用该Activity的Intent对象 Intent intent = getIntent(); Bundle b = new Bundle(); String path = saveBitmap(); b.putString("handwritePath", path); intent.putExtras(b); setResult(RESULT_OK, intent); HandWriteActivity.this.finish(); } else if(v == btn_back){ HandWriteActivity.this.finish(); } } } //保存手写文件 public String saveBitmap(){ //获得系统当前时间,并以该时间作为文件名 SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmss"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String str = formatter.format(curDate); String paintPath = ""; str = str + "write.png"; File dir = new File("/sdcard/notes/"); File file = new File("/sdcard/notes/",str); if (!dir.exists()) { dir.mkdir(); } else{ if(file.exists()){ file.delete(); } } //将view转换成图片 et_handwrite.setDrawingCacheEnabled(true); et_handwrite.setDrawingCacheBackgroundColor(Color.WHITE); Bitmap cutHandwriteBitmap = Bitmap.createBitmap(et_handwrite.getDrawingCache()); et_handwrite.setDrawingCacheEnabled(false); try { //保存绘图文件路径 paintPath = "/sdcard/notes/" + str; FileOutputStream out = new FileOutputStream(file); cutHandwriteBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); out.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return paintPath; } //配置绘图菜单 public void InitPaintMenu(){ ArrayList<Map<String,Object>> menus = new ArrayList<Map<String,Object>>(); for(int i = 0;i < paintItems.length;i++){ Map<String,Object> item = new HashMap<String,Object>(); item.put("image",paintItems[i]); menus.add(item); } paint_bottomMenu.setNumColumns(paintItems.length); paint_bottomMenu.setSelector(R.drawable.bottom_item); SimpleAdapter mAdapter = new SimpleAdapter(HandWriteActivity.this, menus,R.layout.item_button, new String[]{"image"}, new int[]{R.id.item_image}); paint_bottomMenu.setAdapter(mAdapter); } //处理界面 Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); Bundle bundle = new Bundle(); bundle = msg.getData(); Bitmap myBitmap = bundle.getParcelable("bitmap"); InsertToEditText(myBitmap); } }; //将手写字插入到EditText中 private void InsertToEditText(Bitmap mBitmap){ int imgWidth = mBitmap.getWidth(); int imgHeight = mBitmap.getHeight(); //缩放比例 float scaleW = (float) (160f/imgWidth); float scaleH = (float) (200f/imgHeight); Matrix mx = new Matrix(); //对原图片进行缩放 mx.postScale(scaleW, scaleH); mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, imgWidth, imgHeight, mx, true); //将手写的字插入到edittext中 SpannableString ss = new SpannableString("1"); ImageSpan span = new ImageSpan(mBitmap, ImageSpan.ALIGN_BOTTOM); ss.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); et_handwrite.append(ss); } //设置菜单项监听器 class MenuClickEvent implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { switch(position){ //画笔大小 case 0: showPaintSizeDialog(view); break; //颜色 case 1: showPaintColorDialog(view); break; //删除 case 2: Editable editable = et_handwrite.getText(); //找到最后一个手写字,并删除最后一个手写字 int selectionEnd = et_handwrite.getSelectionEnd(); System.out.println("end = "+ selectionEnd); if(selectionEnd < 1){ et_handwrite.setText(""); } else if(selectionEnd == 1){ et_handwrite.setText(""); CharSequence deleteCharSeq = editable.subSequence(0,1); deleteChar.add(deleteCharSeq); } else{ System.out.println("delete"); CharSequence charSeq = editable.subSequence(0, selectionEnd - 1); CharSequence deleteCharSeq = editable.subSequence(selectionEnd - 1,selectionEnd); et_handwrite.setText(charSeq); et_handwrite.setSelection(selectionEnd - 1); //将删除的字存储到列表中,以便恢复使用 deleteChar.add(deleteCharSeq); } break; //恢复 case 3: //取出删除列表中的元素 int length = deleteChar.size(); if(length > 0){ et_handwrite.append(deleteChar.get(deleteChar.size()-1)); deleteChar.remove(deleteChar.size()-1); } break; //清空屏幕 case 4 : if(et_handwrite.getSelectionEnd() > 0){ AlertDialog.Builder builder = new AlertDialog.Builder(HandWriteActivity.this); builder.setTitle("您确定要清空所有吗?"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { et_handwrite.setText(""); dialog.cancel(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); Dialog dialog = builder.create(); dialog.show(); } break; default : break; } } } private int select_handwrite_color_index = 0; private int select_handwrite_size_index = 0; //弹出画笔大小选项对话框 public void showPaintSizeDialog(View parent){ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this,R.style.custom_dialog); alertDialogBuilder.setTitle("选择画笔大小:"); alertDialogBuilder.setSingleChoiceItems(R.array.paintsize, select_handwrite_size_index, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { select_handwrite_size_index = which; touchView.selectHandWritetSize(which); dialog.dismiss(); } }); alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialogBuilder.create().show(); } //弹出画笔颜色选项对话框 public void showPaintColorDialog(View parent){ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this,R.style.custom_dialog); alertDialogBuilder.setTitle("选择画笔颜色:"); alertDialogBuilder.setSingleChoiceItems(R.array.paintcolor, select_handwrite_color_index, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { select_handwrite_color_index = which; touchView.selectHandWriteColor(which); dialog.dismiss(); } }); alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialogBuilder.create().show(); } }
LineEditActivity
package com.llw.notes; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; public class LineEditText extends androidx.appcompat.widget.AppCompatEditText { private Rect mRect; private Paint mPaint; public LineEditText(Context context, AttributeSet attrs) { // TODO Auto-generated constructor stub super(context,attrs); mRect = new Rect(); mPaint = new Paint(); mPaint.setColor(Color.GRAY); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //得到EditText的总行数 int lineCount = getLineCount(); Rect r = mRect; Paint p = mPaint; //为每一行设置格式 for(int i = 0; i < lineCount;i++){ //取得每一行的基准Y坐标,并将每一行的界限值写到r中 int baseline = getLineBounds(i, r); //设置每一行的文字带下划线 canvas.drawLine(r.left, baseline+20, r.right, baseline+20, p); } } }
MainActivity
package com.llw.notes; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.view.View; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private Button bt_add; private SQLiteDatabase db; private DatabaseOperation dop; private ListView lv_notes; private TextView tv_note_id; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //设置为全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ActionBar actionBar=getSupportActionBar(); actionBar.hide(); bt_add = (Button)findViewById(R.id.bt_add); bt_add.setOnClickListener(new ClickEvent()); dop = new DatabaseOperation(this, db); lv_notes = (ListView)findViewById(R.id.lv_notes); //显示记事列表 showNotesList(); //为记事列表添加监听器 lv_notes.setOnItemClickListener(new ItemClickEvent()); lv_notes.setOnItemLongClickListener(new ItemLongClickEvent()); } //记事列表长按监听器 class ItemLongClickEvent implements AdapterView.OnItemLongClickListener { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { tv_note_id = (TextView)view.findViewById(R.id.tv_note_id); int item_id = Integer.parseInt(tv_note_id.getText().toString()); simpleList(item_id); return true; } } //简单列表对话框,用于选择操作 public void simpleList(final int item_id){ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this,R.style.custom_dialog); alertDialogBuilder.setTitle("选择操作"); alertDialogBuilder.setIcon(R.drawable.ic_launcher); alertDialogBuilder.setItems(R.array.itemOperation, new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch(which){ //编辑 case 0 : Intent intent = new Intent(MainActivity.this,AddActivity.class); intent.putExtra("editModel", "update"); intent.putExtra("noteId", item_id); startActivity(intent); break; //删除 case 1 : dop.create_db(); dop.delete_db(item_id); dop.close_db(); //刷新列表显示 lv_notes.invalidate(); showNotesList(); break; } } }); alertDialogBuilder.create(); alertDialogBuilder.show(); } //显示记事列表 private void showNotesList(){ //创建或打开数据库 dop.create_db(); Cursor cursor = dop.query_db(); SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.note_item, cursor, new String[]{"_id","title","time"}, new int[]{R.id.tv_note_id,R.id.tv_note_title,R.id.tv_note_time}); lv_notes.setAdapter(adapter); dop.close_db(); } //记事列表单击监听器 class ItemClickEvent implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { tv_note_id = (TextView)view.findViewById(R.id.tv_note_id); int item_id = Integer.parseInt(tv_note_id.getText().toString()); Intent intent = new Intent(MainActivity.this,AddActivity.class); intent.putExtra("editModel", "update"); intent.putExtra("noteId", item_id); startActivity(intent); finish(); } } class ClickEvent implements View.OnClickListener { @Override public void onClick(View v) { switch(v.getId()){ case R.id.bt_add : Intent intent = new Intent(MainActivity.this,AddActivity.class); intent.putExtra("editModel", "newAdd"); startActivity(intent); finish(); } } } }
PaintActivity
package com.llw.notes; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.GridView; import android.widget.ListView; import android.widget.SimpleAdapter; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class PaintActivity extends Activity { private PaintView paintView; private GridView paint_bottomMenu; private ListView lv_popWindow; //菜单资源 private int[] paintItems = { R.drawable.paint_more, R.drawable.paint_pencil, R.drawable.paint_icon_color, R.drawable.paint_icon_back, R.drawable.paint_icon_forward, R.drawable.paint_icon_delete }; //画笔大小资源 private int[] penceilSizes = { }; private Button btn_save; private Button btn_back; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_paint); paint_bottomMenu = (GridView)findViewById(R.id.paintBottomMenu); paint_bottomMenu.setOnItemClickListener(new MenuClickEvent()); paintView = (PaintView)findViewById(R.id.paint_layout); InitPaintMenu(); btn_save = (Button)findViewById(R.id.bt_save); btn_back = (Button)findViewById(R.id.bt_back); btn_save.setOnClickListener(new ClickEvent()); btn_back.setOnClickListener(new ClickEvent()); } //配置绘图菜单 public void InitPaintMenu(){ ArrayList<Map<String,Object>> menus = new ArrayList<Map<String,Object>>(); for(int i = 0;i < paintItems.length;i++){ Map<String,Object> item = new HashMap<String,Object>(); item.put("image",paintItems[i]); menus.add(item); } paint_bottomMenu.setNumColumns(paintItems.length); paint_bottomMenu.setSelector(R.drawable.bottom_item); SimpleAdapter mAdapter = new SimpleAdapter(PaintActivity.this, menus,R.layout.item_button, new String[]{"image"}, new int[]{R.id.item_image}); paint_bottomMenu.setAdapter(mAdapter); } class ClickEvent implements OnClickListener{ @Override public void onClick(View v) { if(v == btn_save){ //得到调用该Activity的Intent对象 Intent intent = getIntent(); Bundle b = new Bundle(); String path = paintView.saveBitmap(); b.putString("paintPath", path); intent.putExtras(b); setResult(RESULT_OK, intent); PaintActivity.this.finish(); } else if(v == btn_back){ PaintActivity.this.finish(); } } } //设置菜单项监听器 class MenuClickEvent implements OnItemClickListener{ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent; switch(position){ case 0: showMoreDialog(view); break; //画笔大小 case 1: showPaintSizeDialog(view); break; //画笔颜色 case 2: showPaintColorDialog(view); break; //撤销 case 3: paintView.undo(); break; //恢复 case 4 : paintView.redo(); break; //清空 case 5 : AlertDialog.Builder builder = new AlertDialog.Builder(PaintActivity.this,R.style.custom_dialog); builder.setTitle("清空提示"); builder.setMessage("您确定要清空所有吗?"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { paintView.removeAllPaint(); dialog.cancel(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); Dialog dialog = builder.create(); dialog.show(); break; default : break; } } } //弹出画笔颜色选项对话框 public void showPaintColorDialog(View parent){ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this,R.style.custom_dialog); alertDialogBuilder.setTitle("选择画笔颜色:"); alertDialogBuilder.setSingleChoiceItems(R.array.paintcolor, select_paint_color_index, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { select_paint_color_index = which; paintView.selectPaintColor(which); dialog.dismiss(); } }); alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialogBuilder.create().show(); } //弹出画笔大小选项对话框 public void showPaintSizeDialog(View parent){ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this,R.style.custom_dialog); alertDialogBuilder.setTitle("选择画笔大小:"); alertDialogBuilder.setSingleChoiceItems(R.array.paintsize, select_paint_size_index, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { select_paint_size_index = which; paintView.selectPaintSize(which); dialog.dismiss(); } }); alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialogBuilder.create().show(); } private int select_paint_size_index = 0; private int select_paint_style_index = 0; private int select_paint_color_index = 0; //弹出选择画笔或橡皮擦的对话框 public void showMoreDialog(View parent){ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this,R.style.custom_dialog); alertDialogBuilder.setTitle("选择画笔或橡皮擦:"); alertDialogBuilder.setSingleChoiceItems(R.array.paintstyle, select_paint_style_index, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { select_paint_style_index = which; paintView.selectPaintStyle(which); dialog.dismiss(); } }); alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialogBuilder.create().show(); } }
PaintView
package com.llw.notes; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; public class PaintView extends View { private Canvas mCanvas; private Path mPath; private Paint mBitmapPaint; private Bitmap mBitmap; private Paint mPaint; private ArrayList<DrawPath> savePath; private ArrayList<DrawPath> deletePath; private DrawPath dp; private float mX, mY; private static final float TOUCH_TOLERANCE = 4; private int bitmapWidth; private int bitmapHeight; private int currentColor = Color.RED; private int currentSize = 5; private int currentStyle = 1; //设置画笔样式 public void setPaintStyle(){ mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(currentSize); if(currentStyle == 1) mPaint.setColor(currentColor); else{ mPaint.setColor(Color.WHITE); } } //初始化画布 public void initCanvas(){ setPaintStyle(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); //画布大小 mBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.RGB_565); mCanvas = new Canvas(mBitmap); //所有mCanvas画的东西都被保存在了mBitmap中 mCanvas.drawColor(Color.WHITE); mPath = new Path(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); } //画笔颜色 private int[] paintColor = { Color.RED, Color.BLUE, Color.BLACK, Color.GREEN, Color.YELLOW, Color.CYAN, Color.LTGRAY }; //设置画笔样式 public void selectPaintStyle(int which){ if(which == 0){ currentStyle = 1; setPaintStyle(); } //当选择的是橡皮擦时,设置颜色为白色 if(which == 1){ currentStyle = 2; setPaintStyle(); mPaint.setStrokeWidth(20); } } //选择画笔大小 public void selectPaintSize(int which){ int size =Integer.parseInt(this.getResources().getStringArray(R.array.paintsize)[which]); currentSize = size; setPaintStyle(); } //设置画笔颜色 public void selectPaintColor(int which){ currentColor = paintColor[which]; setPaintStyle(); } public PaintView(Context c) { super(c); //得到屏幕的分辨率 DisplayMetrics dm = new DisplayMetrics(); ((Activity) c).getWindowManager().getDefaultDisplay().getMetrics(dm); bitmapWidth = dm.widthPixels; bitmapHeight = dm.heightPixels - 2 * 45; initCanvas(); savePath = new ArrayList<DrawPath>(); deletePath = new ArrayList<DrawPath>(); } public PaintView(Context c, AttributeSet attrs) { super(c,attrs); //得到屏幕的分辨率 DisplayMetrics dm = new DisplayMetrics(); ((Activity) c).getWindowManager().getDefaultDisplay().getMetrics(dm); bitmapWidth = dm.widthPixels; bitmapHeight = dm.heightPixels - 2 * 45; initCanvas(); savePath = new ArrayList<DrawPath>(); deletePath = new ArrayList<DrawPath>(); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); //显示旧的画布 if (mPath != null) { // 实时的显示 canvas.drawPath(mPath, mPaint); } } //路径对象 class DrawPath{ Path path; Paint paint; } /** * 撤销的核心思想就是将画布清空, * 将保存下来的Path路径最后一个移除掉, * 重新将路径画在画布上面。 */ public void undo(){ System.out.println(savePath.size()+"--------------"); if(savePath != null && savePath.size() > 0){ //调用初始化画布函数以清空画布 initCanvas(); //将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中 DrawPath drawPath = savePath.get(savePath.size() - 1); deletePath.add(drawPath); savePath.remove(savePath.size() - 1); //将路径保存列表中的路径重绘在画布上 Iterator<DrawPath> iter = savePath.iterator(); //重复保存 while (iter.hasNext()) { DrawPath dp = iter.next(); mCanvas.drawPath(dp.path, dp.paint); } invalidate();// 刷新 } } /** * 恢复的核心思想就是将撤销的路径保存到另外一个列表里面(栈), * 然后从redo的列表里面取出最顶端对象, * 画在画布上面即可 */ public void redo(){ if(deletePath.size() > 0){ //将删除的路径列表中的最后一个,也就是最顶端路径取出(栈),并加入路径保存列表中 DrawPath dp = deletePath.get(deletePath.size() - 1); savePath.add(dp); //将取出的路径重绘在画布上 mCanvas.drawPath(dp.path, dp.paint); //将该路径从删除的路径列表中去除 deletePath.remove(deletePath.size() - 1); invalidate(); } } /* * 清空的主要思想就是初始化画布 * 将保存路径的两个List清空 * */ public void removeAllPaint(){ //调用初始化画布函数以清空画布 initCanvas(); invalidate();//刷新 savePath.clear(); deletePath.clear(); } /* * 保存所绘图形 * 返回绘图文件的存储路径 * */ public String saveBitmap(){ //获得系统当前时间,并以该时间作为文件名 SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmss"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String str = formatter.format(curDate); String paintPath = ""; str = str + "paint.png"; File dir = new File("/sdcard/notes/"); File file = new File("/sdcard/notes/",str); if (!dir.exists()) { dir.mkdir(); } else{ if(file.exists()){ file.delete(); } } try { FileOutputStream out = new FileOutputStream(file); mBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);//压缩 out.flush(); out.close(); //保存绘图文件路径 paintPath = "/sdcard/notes/" + str; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return paintPath; } private void touch_start(float x, float y) { mPath.reset();//清空path mPath.moveTo(x, y); mX = x; mY = y; } private void touch_move(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { //mPath.quadTo(mX, mY, x, y); mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);//源代码是这样写的,可是我没有弄明白,为什么要这样? mX = x; mY = y; } } private void touch_up() { mPath.lineTo(mX, mY); mCanvas.drawPath(mPath, mPaint); savePath.add(dp); mPath = null; } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath = new Path(); dp = new DrawPath(); dp.path = mPath; dp.paint = mPaint; touch_start(x, y); invalidate(); //清屏 break; case MotionEvent.ACTION_MOVE: touch_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); invalidate(); break; } return true; } }
ShowPicture
package com.llw.notes; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; public class ShowPicture extends AppCompatActivity { private ImageView img; private Bitmap bm; private DisplayMetrics dm; private Matrix matrix = new Matrix(); private Matrix savedMatrix = new Matrix(); private PointF mid = new PointF(); private PointF start = new PointF(); private static int DRAG = 2; private static int ZOOM = 1; private static int NONE = 0; private int mode = 0; private float oldDist = 1f; private static float MINSCALER = 0.3f; private static float MAXSCALER = 3.0f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_picture); //设置为全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ActionBar actionBar=getSupportActionBar(); actionBar.hide(); Button bt_back = (Button)findViewById(R.id.bt_back); bt_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { ShowPicture.this.finish(); } }); Button bt_del = (Button)findViewById(R.id.bt_save); bt_del.setBackgroundResource(R.drawable.paint_icon_delete); dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); //获取分辨率 img = (ImageView)findViewById(R.id.iv_showPic); Intent intent = this.getIntent(); String imgPath = intent.getStringExtra("imgPath"); bm = BitmapFactory.decodeFile(imgPath); //设置居中显示 savedMatrix.setTranslate((dm.widthPixels - bm.getWidth())/2 , (dm.heightPixels - bm.getHeight()) / 2); img.setImageMatrix(savedMatrix); //绑定图片 img.setImageBitmap(bm); //触摸事件 img.setOnTouchListener(new TouchEvent()); } //添加触摸事件,实现图片的手势缩放 class TouchEvent implements View.OnTouchListener { @Override public boolean onTouch(View view, MotionEvent event) { switch(event.getActionMasked()){ //单击触控,用于拖动 case MotionEvent.ACTION_DOWN : matrix.set(img.getImageMatrix()); savedMatrix.set(matrix); start.set(event.getX(), event.getY()); mode = DRAG; break; //多点触控,按下时 case MotionEvent.ACTION_POINTER_DOWN : oldDist = getSpacing(event); savedMatrix.set(matrix); getMidPoint(mid,event); mode = ZOOM; break; //多点触控,抬起时 case MotionEvent.ACTION_POINTER_UP : mode = NONE; break; case MotionEvent.ACTION_MOVE : if(mode == DRAG){ matrix.set(savedMatrix); matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); } //缩放 else if(mode == ZOOM){ //取得多指移动的直径,如果大于10,则认为是缩放手势 float newDist = getSpacing(event); if(newDist > 10){ matrix.set(savedMatrix); float scale = newDist / oldDist; matrix.postScale(scale, scale,mid.x,mid.y); } } break; } img.setImageMatrix(matrix); controlScale(); //setCenter(); center(); return true; } } //求距离 private float getSpacing(MotionEvent event){ float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); } //求中点 private void getMidPoint(PointF mid,MotionEvent event){ float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); mid.set(x / 2, y / 2); } //控制缩放比例 private void controlScale(){ float values[] = new float[9]; matrix.getValues(values); if(mode == ZOOM){ if(values[0] < MINSCALER) matrix.setScale(MINSCALER, MINSCALER); else if(values[0] > MAXSCALER) matrix.setScale(MAXSCALER, MAXSCALER); } } //自动居中 左右及上下都居中 protected void center() { center(true,true); } private void center(boolean horizontal, boolean vertical) { Matrix m = new Matrix(); m.set(matrix); RectF rect = new RectF(0, 0, bm.getWidth(), bm.getHeight()); m.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; if (vertical) { int screenHeight = dm.heightPixels; //手机屏幕分辨率的高度 //int screenHeight = 400; if (height < screenHeight) { deltaY = (screenHeight - height)/2 - rect.top; }else if (rect.top > 0) { deltaY = -rect.top; }else if (rect.bottom < screenHeight) { deltaY = screenHeight - rect.bottom; } } if (horizontal) { int screenWidth = dm.widthPixels; //手机屏幕分辨率的宽度 //int screenWidth = 400; if (width < screenWidth) { deltaX = (screenWidth - width)/2 - rect.left; }else if (rect.left > 0) { deltaX = -rect.left; }else if (rect.right < screenWidth) { deltaX = screenWidth - rect.right; } } matrix.postTranslate(deltaX, deltaY); } }
ShowRecord
package com.llw.notes; import android.content.Intent; import android.graphics.drawable.AnimationDrawable; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; import java.util.Timer; import java.util.TimerTask; public class ShowRecord extends AppCompatActivity { private String audioPath; private int isPlaying = 0; private AnimationDrawable ad_left,ad_right; private Timer mTimer; //语音操作对象 private MediaPlayer mPlayer = null; private ImageView iv_record_wave_left,iv_record_wave_right,iv_microphone; private TextView tv_recordTime; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_record); //设置为全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ActionBar actionBar=getSupportActionBar(); actionBar.hide(); Button bt_back = (Button)findViewById(R.id.bt_back); bt_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { if(isPlaying == 1){ mPlayer.stop(); mPlayer.release(); } ShowRecord.this.finish(); } }); Button bt_del = (Button)findViewById(R.id.bt_save); bt_del.setBackgroundResource(R.drawable.paint_icon_delete); iv_microphone = (ImageView)findViewById(R.id.iv_microphone); iv_microphone.setOnClickListener(new ClickEvent()); Intent intent = this.getIntent(); audioPath = intent.getStringExtra("audioPath"); iv_record_wave_left = (ImageView)findViewById(R.id.iv_record_wave_left); iv_record_wave_right = (ImageView)findViewById(R.id.iv_record_wave_right); // ad_left = (AnimationDrawable)iv_record_wave_left.getBackground(); // ad_left = (AnimationDrawable)iv_record_wave_left.getBackground(); iv_record_wave_left.setImageResource(R.drawable.record_wave_left); iv_record_wave_right.setImageResource(R.drawable.record_wave_right); ad_left=((AnimationDrawable) iv_record_wave_left.getDrawable()); ad_right=((AnimationDrawable) iv_record_wave_right.getDrawable()); tv_recordTime = (TextView)findViewById(R.id.tv_recordTime); } final Handler handler = new Handler(){ public void handleMessage(Message msg) { switch(msg.what){ case 1 : String time[] = tv_recordTime.getText().toString().split(":"); int hour = Integer.parseInt(time[0]); int minute = Integer.parseInt(time[1]); int second = Integer.parseInt(time[2]); if(second < 59){ second++; } else if(second == 59 && minute < 59){ minute++; second = 0; } if(second == 59 && minute == 59 && hour < 98){ hour++; minute = 0; second = 0; } time[0] = hour + ""; time[1] = minute + ""; time[2] = second + ""; //调整格式显示到屏幕上 if(second < 10) time[2] = "0" + second; if(minute < 10) time[1] = "0" + minute; if(hour < 10) time[0] = "0" + hour; //显示在TextView中 tv_recordTime.setText(time[0]+":"+time[1]+":"+time[2]); break; } } }; class ClickEvent implements View.OnClickListener { @Override public void onClick(View arg0) { // TODO Auto-generated method stub //试听 if(isPlaying == 0){ isPlaying = 1; mPlayer = new MediaPlayer(); tv_recordTime.setText("00:00:00"); mTimer = new Timer(); mPlayer.setOnCompletionListener(new MediaCompletion()); try { mPlayer.setDataSource(audioPath); mPlayer.prepare(); mPlayer.start(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mTimer.schedule(new TimerTask() { @Override public void run() { Message message = new Message(); message.what = 1; handler.sendMessage(message); } }, 1000,1000); //播放动画 ad_left.start(); ad_right.start(); } //结束试听 else{ isPlaying = 0; mPlayer.stop(); mPlayer.release(); mPlayer = null; mTimer.cancel(); mTimer = null; //停止动画 ad_left.stop(); ad_right.stop(); } } } class MediaCompletion implements MediaPlayer.OnCompletionListener { @Override public void onCompletion(MediaPlayer mp) { mTimer.cancel(); mTimer = null; isPlaying = 0; //停止动画 ad_left.stop(); ad_right.stop(); Toast.makeText(ShowRecord.this, "播放完毕", Toast.LENGTH_SHORT).show(); tv_recordTime.setText("00:00:00"); } } }
TouchView
package com.llw.notes; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.View; import java.util.Timer; import java.util.TimerTask; public class TouchView extends View { private Bitmap mBitmap,myBitmap; private Canvas mCanvas; private Path mPath; private Paint mBitmapPaint; private Paint mPaint; private Handler bitmapHandler; GetCutBitmapLocation getCutBitmapLocation; private Timer timer; DisplayMetrics dm; private int w,h; private int currentColor = Color.RED; private int currentSize = 5; //画笔颜色 private int[] paintColor = { Color.RED, Color.BLUE, Color.BLACK, Color.GREEN, Color.YELLOW, Color.CYAN, Color.LTGRAY }; //设置画笔样式 public void setPaintStyle(){ mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(currentSize); mPaint.setColor(currentColor); } //设置画笔的大小 public void selectHandWritetSize(int which){ int size =Integer.parseInt(this.getResources().getStringArray(R.array.paintsize)[which]); currentSize = size; setPaintStyle(); } //设置画笔颜色 public void selectHandWriteColor(int which){ currentColor = paintColor[which]; setPaintStyle(); } public TouchView(Context context) { super(context); dm = new DisplayMetrics(); ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm); w = dm.widthPixels; h = dm.heightPixels; initPaint(); } public TouchView(Context context, AttributeSet attrs) { super(context,attrs); dm = new DisplayMetrics(); ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm); w = dm.widthPixels; h = dm.heightPixels; initPaint(); } //设置handler public void setHandler(Handler mBitmapHandler){ bitmapHandler = mBitmapHandler; } //初始化画笔,画布 private void initPaint(){ //设置画笔样式 setPaintStyle(); getCutBitmapLocation = new GetCutBitmapLocation(); //画布大小 mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); //所有mCanvas画的东西都被保存在了mBitmap中 mCanvas.drawColor(Color.TRANSPARENT); mPath = new Path(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); timer = new Timer(true); } /** * 处理屏幕显示 */ Handler handler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what) { case 1: myBitmap = getCutBitmap(mBitmap); Message message = new Message(); message.what=1; Bundle bundle = new Bundle();; bundle.putParcelable("bitmap",myBitmap); message.setData(bundle); bitmapHandler.sendMessage(message); RefershBitmap(); break; } super.handleMessage(msg); } }; /** * 发送消息给handler更新ACTIVITY */ TimerTask task = new TimerTask() { public void run() { Message message = new Message(); message.what=1; Log.i("线程", "来了"); handler.sendMessage(message); } }; //切割画布中的字并返回 public Bitmap getCutBitmap(Bitmap mBitmap){ //得到手写字的四周位置,并向外延伸10px float cutLeft = getCutBitmapLocation.getCutLeft() - 10; float cutTop = getCutBitmapLocation.getCutTop() - 10; float cutRight = getCutBitmapLocation.getCutRight() + 10; float cutBottom = getCutBitmapLocation.getCutBottom() + 10; cutLeft = (0 > cutLeft ? 0 : cutLeft); cutTop = (0 > cutTop ? 0 : cutTop); cutRight = (mBitmap.getWidth() < cutRight ? mBitmap.getWidth() : cutRight); cutBottom = (mBitmap.getHeight() < cutBottom ? mBitmap.getHeight() : cutBottom); //取得手写的的高度和宽度 float cutWidth = cutRight - cutLeft; float cutHeight = cutBottom - cutTop; Bitmap cutBitmap = Bitmap.createBitmap(mBitmap, (int)cutLeft, (int)cutTop, (int)cutWidth, (int)cutHeight); if (myBitmap!=null ) { myBitmap.recycle(); myBitmap= null; } return cutBitmap; } //刷新画布 private void RefershBitmap(){ initPaint(); invalidate(); if(task != null) task.cancel(); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); //显示旧的画布 canvas.drawPath(mPath, mPaint); //画最后的path } private float mX, mY; private static final float TOUCH_TOLERANCE = 4; //手按下时 private void touch_start(float x, float y) { mPath.reset();//清空path mPath.moveTo(x, y); mX = x; mY = y; if(task != null) task.cancel();//取消之前的任务 task = new TimerTask() { @Override public void run() { Message message = new Message(); message.what=1; Log.i("线程", "来了"); handler.sendMessage(message); } }; getCutBitmapLocation.setCutLeftAndRight(mX,mY); } //手移动时 private void touch_move(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { mPath.quadTo(mX, mY, x, y); // mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);//源代码是这样写的,可是我没有弄明白,为什么要这样? mX = x; mY = y; if(task != null) task.cancel();//取消之前的任务 task = new TimerTask() { @Override public void run() { Message message = new Message(); message.what=1; Log.i("线程", "来了"); handler.sendMessage(message); } }; getCutBitmapLocation.setCutLeftAndRight(mX,mY); } } //手抬起时 private void touch_up() { //mPath.lineTo(mX, mY); mCanvas.drawPath(mPath, mPaint); mPath.reset(); if (timer!=null) { if (task!=null) { task.cancel(); task = new TimerTask() { public void run() { Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; timer.schedule(task, 1000, 1000); //2200秒后发送消息给handler更新Activity } }else { timer = new Timer(true); timer.schedule(task, 1000, 1000); //2200秒后发送消息给handler更新Activity } } //处理界面事件 @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { //down表示手势事件开始,up表示结束,move则代表着过程 case MotionEvent.ACTION_DOWN: touch_start(x, y); invalidate(); //刷新 break; case MotionEvent.ACTION_MOVE: touch_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); invalidate(); break; } return true; } }
3,最后res中drawable文件layout文件values文件粘贴上去就行了
功能可以看代码注释,不会可以在评论区提问我会解答。
本程序大家供学习使用。
我把源代码发到github上方便大家看代码学习:
网址:https://github.com/Rockffer/notes/tree/master
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。