基于Java实现的简单便签app设计

一、实验题目

本设计主要是实现一个简单的便签软件主界面实现双视图预览——单列显示、瀑布流显示主界面可以对文本进行批量删除、加锁、按文本内容搜索等功能主界面可以将本地数据库同步到云端服务器的数据库上,也可以拉取云端服务器的数据库文本内容而富文本编辑界面,可以编写文本,并实现加粗、斜体等功能,也可以插入图片,记录当前修改时间,并保存到本地数据库;实现转发、删除、加锁;筛选界面可以根据写作日期,展示一年内几个月写了多少篇文章,并通过勾选筛选出相应的文本在主界面显示

二、实现内容

  • 富文本界面的编辑文本功能,并记录当前修改时间
  • 转发功能
  • 加锁功能
  • 删除文本

三、课堂实验结果 A. 实验截图

3.1 实验步骤以及关键代码

3.1.1 RichEditor 的实现

其中 exec 用于执行 js 代码

总之,编辑器的核心功能由 js 实现,RichEditor 封装了 js 的功能,为上层提供了 Java 接口。

3.1.2 RichEditor 相应功能的实现

居中、加粗、斜体、中划线、撤销操作的实现

居中功能需要判断是否点击多次,点击一次居中,点击两次则为正常文档流——居左而加粗、中划线、斜体在执行 js 代码时会实现偶次数执行代码取消相应的效果

插入图片功能的实现插入图片是实现富文本编辑功能的难点基本思路是:从相册或者照相获取图片——裁剪图片——保存图片到本地(使用保存时间作为文件名)——使用本地链接显示到富文本编辑器上 从相册或照相获取图片

相册 Intent

Intent intent = new Intent() ;
intent.setType("image/*") ;
// 调用系统相册
intent.setAction(Intent.ACTION_GET_CONTENT) ;
startActivityForResult(intent,1);
// 打开相册的回调函数
if ( requestCode==1 ){
if ( data!=null ){
Uri uri = data.getData(); // 获取返回的uri
cutImg(uri); // 调用剪切函数
}
}

照相 Intent

Intent intent = new Intent();
// 调用系统的照相机
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = Uri.parse("file://" + "/" +
Environment.getExternalStorageDirectory().getPath()
+ "/" + "tmp.jpg");
// 将返回的数据直接保存到tmp.jpg,并将其uri保存为imageUri
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, 3);
// 打开相机的回调函数
if ( requestCode == 3 ){
    
    
cutImg(imageUri); // 将保存的tmp.jpg转化的Uri传给剪切函数
}

剪切图片

通过调用系统剪切 Intent 进行剪切动作

// 裁剪图片
void cutImg(Uri uri) {
    
    
if (uri != null) {
    
    
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
//true:出现裁剪的框
intent.putExtra("crop", "true");
//裁剪宽高时的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);

//裁剪后的图片的大小
intent.putExtra("outputX", 150);
intent.putExtra("outputY", 150);
/**
* 此方法返回的图片只能是小图片(sumsang测试为高宽160px的图片)
* 故将图片保存在Uri中,调用时将Uri转换为Bitmap
* 此方法还可解决miui系统不能return data的问题
*/
//uritempFile为Uri类变量,实例化uritempFile
uriTempFile = Uri.parse("file://" + "/" +
Environment.getExternalStorageDirectory().getPath()
+ "/" + "small.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriTempFile);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, 2);
}
else {
    
     return; }
}

// 打开系统裁剪界面的回调函数
if (requestCode == 2) {
    
    
if (data != null) {
    
    
//将Uri图片转换为Bitmap
Bitmap bitmap = null;
try {
    
    
bitmap = BitmapFactory.decodeStream(getContentResolver()
.openInputStream(uriTempFile));
} catch (FileNotFoundException e) {
    
     e.printStackTrace(); }
//保存到图片到本地
saveImg(bitmap);
} else {
    
     return; }
}

保存图片

// 保存图片
void saveImg(Bitmap bitmap) {
    
    
try {
    
    
// 创建文件夹路径
File destDir = new File(fileBasePath);
if (!destDir.exists()) {
    
     // 如果不存在该文件夹,则创建该文件夹
destDir.mkdirs();
}
// 创建图片文件,路径为上文的文件夹子目录,将此时系统时间作为图片文件名
File f = new File(fileBasePath + System.currentTimeMillis()+ ".png");
f.createNewFile();
//输出流
FileOutputStream out = new FileOutputStream(f);
/** mBitmap.compress 压缩图片
* Bitmap.CompressFormat.PNG 图片的格式
* 100 图片的质量(0‐100)
* out 文件输出流
*/
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
// 将该图片插入富文本编辑器中
richEditor.insertImage(filePath,"png");
} catch (IOException e) {
    
     e.printStackTrace(); }
}

使用 Dialog 实现一个从底部向上弹出的菜单栏,用于选择图片来源,相册或者相机

// 选择相册或相机的dialog
void setPictureMenuDialog(){
    
    
pictureMenu = new Dialog(this,R.style.bottom_dialog) ;
//填充对话框的布局
final LinearLayout linearLayout =
(LinearLayout) LayoutInflater.from(this)
.inflate(R.layout.layout_picture_menu, null);
//将布局设置给Dialog
pictureMenu.setContentView(linearLayout);
//按键初始化
cameraBtn = (Button) linearLayout.findViewById(R.id.cameraBtn);
albumBtn = (Button) linearLayout.findViewById(R.id.albumBtn);
//获取当前Activity所在的窗体
Window dialogWindow = pictureMenu.getWindow();
//设置Dialog从窗体底部弹出
dialogWindow.setGravity(Gravity.BOTTOM);
// 设置Dialog动画
dialogWindow.setWindowAnimations(R.style.dialog_style);
//获得窗体的属性
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
// 窗体距离底部的距离
lp.y = 150+20; // 150为虚拟机虚拟键盘的高度
// 窗体的高度、宽度和透明度
lp.width = getResources().getDisplayMetrics().widthPixels‐50; // 宽度
linearLayout.measure(0, 0);
lp.height = linearLayout.getMeasuredHeight(); // 获取layout的高度
lp.alpha = 9f; // 设置窗体的透明度
// 将属性设置给窗体
dialogWindow.setAttributes(lp);
// 点击外界面时撤除Diglog
pictureMenu.setCanceledOnTouchOutside(true);
// 显示Diglog
pictureMenu.show();
// 按键响应
PictureMenuRespond() ;
}

保存html代码到本地数据库,读取html代码到富文本编辑器

// 获得编辑器的html代码
richEditor.getHtml();
// 读取html代码到编辑器中
richEditor.setHtml(htmlCode);

  • 保存 HTML 代码到本地数据库,读取 HTML 代码到富文本编辑器
  • 实现监听软键盘弹出收起——弹出时显示编辑器工具(撤销、插图等),收起时显示便签工具(转发、加锁等)并取消编辑器焦点
  • 实现监听类:根据根视图在屏幕中显示的大小判断是否弹出软键盘

实现监听事件

便签工具相应功能的实现

// 软键盘弹出收起的监听响应
void softKeyBoardListener(){
    
    
SoftKeyBoardListener.setListener(
NoteActivity.this,
new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
    
    
@Override
public void keyBoardShow(int height) {
    
    
// Toast.makeText(NoteActivity.this,"键盘显示",Toast.LENGTH_SHORT).show();
editTool.setVisibility(View.VISIBLE);
noteTool.setVisibility(View.GONE);
}
@Override
public void keyBoardHide(int height) {
    
    
// Toast.makeText(NoteActivity.this,"键盘隐藏",Toast.LENGTH_SHORT).show();
richEditor.clearFocus() ;
editTool.setVisibility(View.GONE);
noteTool.setVisibility(View.VISIBLE);
}
});
}

转发功能:直接调用系统的转发功能

findViewById(R.id.shareBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, richEditor.getHtml());
intent.setType("text/plain");
startActivity(Intent.createChooser(intent,"分享给"));
}
});

删除功能

findViewById(R.id.delBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(NoteActivity.this);
alertDialog.setTitle("是否删除")
.setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 如果原先存在该便签,则从数据库中删除
if( id>0 ){
db_helper.getWritableDatabase()
.execSQL("DELETE FROM Article WHERE id =" + id + " ");
}
// 否则直接结束编辑界面即可
finish();
}
})
.setNegativeButton("否", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {}
})
.create().show();
}
});

加锁功能

findViewById(R.id.lockBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 自定义对话框:LayoutInflater
LayoutInflater layoutInflater = LayoutInflater.from(NoteActivity.this);
View alertDialogLayout = layoutInflater.inflate(R.layout.layout_dialog,null);
final TextView passwordET = (TextView)
alertDialogLayout.findViewById(R.id.passwordET) ;
final TextView repetitionET = (TextView)
alertDialogLayout.findViewById(R.id.repetitionET) ;
AlertDialog.Builder alertDialog = new AlertDialog.Builder(NoteActivity.this);
alertDialog.setView(alertDialogLayout)
.setTitle("修改/添加密码")
.setPositiveButton("保存", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String password = passwordET.getText().toString() ;
String repetition = repetitionET.getText().toString() ;
if( !password.equals(repetition) )
Toast.makeText(NoteActivity.this,
"重复密码有误",Toast.LENGTH_SHORT).show();
else{
// 使用MD5加密密码
pass = MD5Utils.md5Password(password) ;
}
}
})
.setNegativeButton("放弃", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {}
})
.create().show();
}
});

回传数据保存到数据库中(返回键的操作跟下面一样)

//重写返回键的操作
@Override
public void onBackPressed(){
if ( id>0 ){ // 如果是修改文本
// 修改文本:回写到数据库
String sql = "UPDATE Article set article='" + richEditor.getHtml() + "'" ;
// 如果过程有加密,则回传时将标签locked设为1,并将密码赋给password属性
if ( !pass.equals("") ) sql += ", locked="+1+", password='"+pass+"'" ;
sql += " WHERE id="+id ;
db_helper.getWritableDatabase().execSQL(sql);
}
else{ // 如果是新建文本
// 获取当前时间——年月日
Calendar calendar=Calendar.getInstance();
ContentValues values = new ContentValues() ;
values.put("article",richEditor.getHtml());
values.put("year",calendar.get(Calendar.YEAR));
values.put("month",calendar.get(Calendar.MONTH)+1);
values.put("day",calendar.get(Calendar.DAY_OF_MONTH));
// 之前保存的进入编辑器的事件
values.put("time",time);
// 判断是否有加锁
if ( pass.equals("") ) values.put("locked",0);
else{
values.put("locked",1);
values.put("password",pass);
}
// 插入数据库新文本
db_helper.getWritableDatabase().insert("Article",null,values) ;
}
finish() ;
}

至此,关于富文本编辑器的内容实现结束
calendar.get(Calendar.MONTH)+1);
values.put(“day”,calendar.get(Calendar.DAY_OF_MONTH));
// 之前保存的进入编辑器的事件
values.put(“time”,time);
// 判断是否有加锁
if ( pass.equals("") ) values.put(“locked”,0);
else{
values.put(“locked”,1);
values.put(“password”,pass);
}
// 插入数据库新文本
db_helper.getWritableDatabase().insert(“Article”,null,values) ;
}
finish() ;
}








至此,关于富文本编辑器的内容实现结束

猜你喜欢

转载自blog.csdn.net/newlw/article/details/125053809