一,功能
拍照
添加画板
录音
书写转文字
添加图片
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文件粘贴上去就行了
文章来源:https://www.toymoban.com/news/detail-508098.html
功能可以看代码注释,不会可以在评论区提问我会解答。
本程序大家供学习使用。
我把源代码发到github上方便大家看代码学习:
网址:https://github.com/Rockffer/notes/tree/master文章来源地址https://www.toymoban.com/news/detail-508098.html
到了这里,关于Android——多功能记事本(Android Studio)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!