安卓 Android之开发简单小应用(三)
一、简述
一个简单的txt文本编辑器。
工程打包:链接: https://pan.baidu.com/s/1jO7tqv_HI-ubfuNV3IxVVA 提取码: 47zr
蓝奏:https://www.lanzous.com/i2fy0yf
二、效果
三、工程结构
四、源文件
TxtReader.java文件
package com.liang.notes;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Timer;
import java.util.TimerTask;
import com.liang.notes.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.text.InputFilter;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridLayout;
import android.widget.TextView;
import android.widget.Toast;
public class TxtReader extends Activity implements OnClickListener {
/** Called when the activity is first created. */
private String filePath = "";//保存文件的绝对路径
private String fileName = "";//文件名
@SuppressLint("NewApi") @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//设置为没有标题栏,自定义一个标签作为标题
setContentView(R.layout.main);//设置布局
//获取控件对象,并监听点击事件
Button fileOpenBtn = (Button)findViewById(R.id.btn_open);
fileOpenBtn.setOnClickListener(new OpenFileAction());
Button btnexit = (Button)findViewById(R.id.btn_exit);
btnexit.setOnClickListener(this);
Button btnsave = (Button)findViewById(R.id.btn_save);
btnsave.setOnClickListener(this);
Button btnsaveas = (Button)findViewById(R.id.btn_saveas);
btnsaveas.setOnClickListener(this);
Button btnfind = (Button)findViewById(R.id.btn_find);
btnfind.setOnClickListener(this);
Button btnnew = (Button)findViewById(R.id.btn_new);
btnnew.setOnClickListener(this);
//如果是文件关联方式打开文件
try
{
Intent intent = getIntent();
if(intent.getType().equals("text/plain"))
{
readFile( intent.getData().getPath() );
}
}catch(Exception e){}
}
@Override //子页面返回时执行
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == 1 && resultCode == 1){//有多个页面时根据请求码和结果码判断是哪一个子页面结束返回,并相应的做出响应
Bundle bunde=data.getExtras();//获取数据束
readFile( bunde.getString("path") );//类似于键值对,根据键"path"获取对应的值(子页面传回来的数据)
}
}
private void readFile(String path)//根据文件爱你绝对路径打开文件
{
if(!path.equals("") && !path.trim().equals(""))//文件名不为空
{
filePath = path;
fileName = filePath.substring(filePath.lastIndexOf("/")+1,filePath.length());//根据绝对路径得到文件名,(用来设置标题)
TextView tvtitle = (TextView)findViewById(R.id.tv_title);//获取便签对象,作为标题
try
{
tvtitle.setText(fileName+"-我的记事本");//设置文本
EditText tv = (EditText) findViewById(R.id.edt_contents);//获取到多行编辑框
String code = jugeCode();//简单判断文件编码
String fileContent = getStringFromFile(code);//获取到文件内容
tv.setText(fileContent);//将编辑框的内容设置为文件内容
}
catch(Exception e)
{
filePath = "";
fileName = "";
Toast.makeText(this, "获取数据异常",Toast.LENGTH_SHORT).show();
}
}
}
public String jugeCode()//简单的判断应该用什么编码打开文件
{
String code = "UTF8";
String content = getStringFromFile(code);// 用UTF-8编码读取
if( content.contains("�"))//出现"�"的情况,可能是中文
{
code = "GB2312";//将编码设置为 GB2312
content = getStringFromFile(code);// 再次读取
if( content.contains("�"))//出现"�"的情况,可能是Unicode
{
code = "Unicode";//将编码设置为 Unicode
}
}
return code;
}
public String getStringFromFile(String code)//按照一定的编码格式读取txt文件
{
try {
StringBuffer sBuffer = new StringBuffer();//用来存放文件内容
FileInputStream fInputStream = new FileInputStream(filePath);//根据绝对路径创建数据流
InputStreamReader inputStreamReader = new InputStreamReader(fInputStream, code);//按照code创建输入流
BufferedReader in = new BufferedReader(inputStreamReader);
if(!new File(filePath).exists())//如果文件不存在
{
in.close();//关闭流
return null;//直接返回
}
while (in.ready())
{
sBuffer.append(in.readLine() + "\n");//一行一行的读取,并追加到sBuffer中
}
in.close();//关闭流
return sBuffer.toString();//返回文件内容
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
class OpenFileAction implements OnClickListener
{
public void onClick(View v) {//这是另外一种方式实现监听
//"打开"按钮的监听事件处理,跳转到文件列表界面
Intent in = new Intent(TxtReader.this, ListAllFileActivity.class);
startActivityForResult(in, 1);//设置请求码为1
}
}
@SuppressLint("NewApi")
@Override
public void onClick(View arg) {//监听事件处理
switch (arg.getId())
{
case R.id.btn_new://新建按钮
EditText tv = (EditText) findViewById(R.id.edt_contents);//获取到文本编辑框对象
tv.setText("");//清空内容
filePath = "";//清空路径
fileName = "";//清空文件名
TextView tvtitle = (TextView)findViewById(R.id.tv_title);//获取到标题标签
tvtitle.setText("未命名.txt-我的记事本");//设置文本
break;
case R.id.btn_save://保存按钮
if(fileName.isEmpty())//文件名为空,说明是新建文件(未命名)
{
//弹出对话框,让用户输入文件名
AlertDialog.Builder builderSave = new AlertDialog.Builder(this);
builderSave.setTitle("保存"); //对话框标题
builderSave.setMessage("请输入文件名!");//对话框提示信息
final EditText edtname = new EditText(this);//创建一个输入框对象
//设置文件名输入框属性
edtname.setSingleLine();//设置为单行输入
edtname.setText("未命名.txt");//设置文本
edtname.setSelection(0, 3);//选中文本的第0开始的3个字符(就是选中"未命名"3个字符)
edtname.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置输入最大长度
});
builderSave.setView(edtname);//将输入框添加到对话框
builderSave.setNegativeButton("取消",null); //添加取消按钮
//添加确定按钮,并且添加单击事件处理
builderSave.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String name = edtname.getText().toString().trim();//获取输入框的文本内容,并去掉前后空格
if(!(name.isEmpty()))//如果输入的文件名不为空
{
if(!name.endsWith(".txt"))//文件名没有以".txt"结尾
{
name += ".txt";//在结尾处添加".txt"
}
fileName = name;//更新为当前文件名
//获取文本编辑框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
//将文本编辑框内容保存到文件
boolean b = Save(name,edtcontent.getText().toString(),true);
if(b)
{
TextView tvtitle = (TextView)findViewById(R.id.tv_title);//获取到标题标签
tvtitle.setText(fileName+"-我的记事本");//设置文本
//弹出小黑框提示
Toast.makeText(TxtReader.this,"已保存",Toast.LENGTH_SHORT).show();
}
}
else//文件名为空
{
//提示
Toast.makeText(TxtReader.this,"文件名不能为空",Toast.LENGTH_SHORT).show();
}
}
});
builderSave.show();//弹出保存对话框
//等待对话框弹出之后,再弹出软键盘
new Timer().schedule(new TimerTask() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(edtname, 0);
}
},300);
}
else //文件名不为空,说明是打开的文件,或者是已经保存过一次的文件
{
if(!fileName.endsWith(".txt"))//文件名不以".txt"结尾
{
fileName += ".txt";//在结尾加上".txt"
}
//获取文本输入框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
//获取文本输入框的内容
String txt = edtcontent.getText().toString();
//System.out.println(txt);
//覆盖保存到文件中,
boolean b = Save(fileName,txt,false);
//提示保存成功
if(b)Toast.makeText(TxtReader.this,"已保存",Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_saveas://另存为按钮
if(true)
{
//弹出文件两寸为对话框
AlertDialog.Builder builderSaveas = new AlertDialog.Builder(this);
builderSaveas.setTitle("另存为");//设置标题
builderSaveas.setMessage("请输入文件名!");//设置提示信息
final EditText edtname = new EditText(this);//创建一个输入框对象
//设置文件名输入框属性
edtname.setSingleLine();//设置为单行输入
edtname.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置输入最大长度
});
if(filePath.isEmpty())//如果原来文件名为空,说明是新建文件
{
edtname.setText("未命名.txt");//设置文本
edtname.setSelection(0, 3);//选中文本的第0开始的3个字符(就是选中"未命名"3个字符)
}
else //如果原来文件名不为空,说明是不是新建文件
{
//确保文件名是以".txt"结尾的
if(!fileName.endsWith(".txt"))
{
fileName += ".txt";
}
edtname.setText(fileName);//将文本框初始文本为原来的文件名
int top = fileName.indexOf(".txt")+1;
edtname.setSelection(0, top);//选中原来的文件名
}
builderSaveas.setView(edtname);//将编辑框添加到另存为对话框
builderSaveas.setNegativeButton("取消",null); //添加取消按钮
//添加确定按钮,并监听点击事件
builderSaveas.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String name = edtname.getText().toString().trim();//获取输入框的内容并去掉两端的空格
if(!(name.isEmpty()))//如果文件名不为空
{
//确保文件名以".txt"结尾
if(!name.endsWith(".txt"))
{
name += ".txt";
}
fileName = name;//设置当前文件名
//获取文本输入框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
//将文件内容覆盖保存
boolean b = Save(name,edtcontent.getText().toString(),false);
//提示保存成功
if(b) Toast.makeText(TxtReader.this,"已保存",Toast.LENGTH_SHORT).show();
}
else//文件名为空
{
Toast.makeText(TxtReader.this,"文件名不能为空",Toast.LENGTH_SHORT).show();
}
}
});
builderSaveas.show();//弹出另存为对话框
//等待对话框弹出之后,再弹出软键盘
new Timer().schedule(new TimerTask() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(edtname, 0);
}
},300);
}
break;
case R.id.btn_find://查找按钮
//查找、替换对话框
AlertDialog.Builder builder = new AlertDialog.Builder(TxtReader.this);
builder.setTitle("查找/替换"); //设置标题
//创建一个网格布局
GridLayout grid = new GridLayout(TxtReader.this);
grid.setColumnCount(2);//设置列数
//创建替换为标签
TextView viewrpl = new TextView(TxtReader.this);
viewrpl.setText("替换为:");//设置文本
//创建替换文本输入框
final EditText edtrpl = new EditText(TxtReader.this);
edtrpl.setSingleLine();//设置为单行
edtrpl.setHeight(45);//设置高度
edtrpl.setPadding(3, 0, 3, 0);//设置内边距,左上右下
edtrpl.setHint("请输入替换为的字符");//设置初始文本(获取焦点是次文本消失)
edtrpl.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置最大长度
});
grid.addView(viewrpl, 0);//将替换为标签添加到网格布局的第0列
grid.addView(edtrpl, 1);//将替换为输入框添加到网格布局的第1列
//创建查找标签
TextView viewfind = new TextView(TxtReader.this);
viewfind.setText("查找:");//设置文本
//创建查找输入框
final EditText edtfind = new EditText(TxtReader.this);
edtfind.setSingleLine();//设置为单行
edtfind.setHeight(45);//设置高度
edtfind.setPadding(3, 0, 3, 0);//设置内边距
edtfind.setHint("请输入要查找的字符");//设置初始字符
edtfind.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置最大长度
});
grid.addView(viewfind, 0);//将查找标签添加到网格布局的第0列
grid.addView(edtfind, 1);//将查找输入框添加到网格布局的第1列
builder.setView(grid);//将网格布局添加到对话框
builder.setNegativeButton("取消",null); //添加取消按钮
//添加查找按钮并监听点击事件
builder.setNeutralButton("查找", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String findStr = edtfind.getText().toString();//获取到要查找的文本
if(findStr.isEmpty())//为空,什么都不做
{
}
else//不为空
{
//获取文本编辑框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
int start = -1;//选中文本的开始索引
//在全部内容中查找目标,并记下找到的开始位置
start = edtcontent.getText().toString().indexOf(findStr);
if(start != -1)//已经找到
{
int stop = start+findStr.length();//选中文本的结束索引
edtcontent.setSelection(start, stop);//将找到的文本选中
//提示找到
Toast.makeText(TxtReader.this,"已找到!",Toast.LENGTH_SHORT).show();
}
else//未找到
{
Toast.makeText(TxtReader.this,"未找到!",Toast.LENGTH_SHORT).show();
}
}
}
});
//添加替换按钮
builder.setPositiveButton("替换", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//String rplstr = edtrpl.getText().toString();//获取到要替换为的文本
Toast.makeText(TxtReader.this,"替换成功!",Toast.LENGTH_SHORT).show();
}
});
builder.show(); //弹出对话框
break;
case R.id.btn_exit://退出按钮
//退出确认对话框
AlertDialog.Builder builderExit = new AlertDialog.Builder(this);
builderExit.setTitle("退出"); //标题
builderExit.setMessage("您确定退出吗?");//提示信息
builderExit.setNegativeButton("取消",null);//添加取消按钮
//添加确定按钮
builderExit.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//判断文件是否有修改并且尚未保存,如果有应该提示用户。。。
finish();//关闭页面
}
});
builderExit.show();
break;
}
}
//保存到文件 filename:文件名 content:内容 isAppend:是否追加,(否则覆盖)
public static boolean Save(String filename,String content,boolean isAppend)
{
//在文本文本中追加内容
String sdCardDir =Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(sdCardDir,filename);
BufferedWriter out = null;
try {
if(!file.exists())//文件不存在
{
file.createNewFile();//创建新文件
}
FileOutputStream outStream = new FileOutputStream(file,isAppend);
outStream.write(content.getBytes());//写入文件
outStream.close();//关闭流
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(out != null){
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
ListAllFileActivity.java文件
package com.liang.notes;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.liang.notes.R;
import android.annotation.SuppressLint;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
/*展现全部文件的Activity*/
public class ListAllFileActivity extends ListActivity {
/*文件列表*/
private List fileNameList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.filelist);//设置布局
//初始化文件列表
File path = android.os.Environment.getExternalStorageDirectory();
File[] f = path.listFiles();
fill(f);
}
@Override //选项点击事件
protected void onListItemClick(ListView l, View v, int position, long id) {
//bundle = new Bundle();
File file = fileNameList.get(position);
if (file.isDirectory())//如果是文件夹,则进入
{
File[] f = file.listFiles();
fill(f);
}
else //如果是文件
{
//将选中的文件的绝对路径返回给主页面
Intent intent = new Intent(ListAllFileActivity.this, TxtReader.class);
//bundle.putString(fileNameKey, file.getAbsolutePath());
intent.putExtra("path",file.getAbsolutePath());
setResult(1, intent);//设置返回码为1
finish();
}
}
// 读取文件列表,并设置listview
private void fill(File[] files) {
fileNameList = new ArrayList();
for (File file : files) {
if (isValidFileOrDir(file)) {
fileNameList.add(file);
}
}
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, fileToStrArr(fileNameList));
setListAdapter(adapter);
}
/*检查是否为合法的文件名,或者是否为路径*/
@SuppressLint("DefaultLocale") private boolean isValidFileOrDir(File file)
{
if (file.isDirectory()) {
return true;
}
else {
String fileName = file.getName().toLowerCase();
if (fileName.endsWith(".txt")) {
return true;
}
}
return false;
}
private String[] fileToStrArr(List fl)
{
ArrayList fnList = new ArrayList();
for (int i = 0; i < fl.size(); i++) {
String nameString = fl.get(i).getName();
fnList.add(nameString);
}
return fnList.toArray(new String[0]);
}
}
AndroidManifet.xml文件
main.xml
五、总结
1、添加对储存卡的读写权限
2、弹出文件名输入框同时弹出软键盘(输入法)
需要等待对话框创建完毕。
//等待对话框弹出之后,再弹出软键盘
new Timer().schedule(new TimerTask() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(edtname, 0);
}
},300);
3、应用图标设置
4、将应用关联txt文件类型
也就是点击txt文件,让自己的app出现在txt格式文件的默认打开列表中。
在AnsroidManifest.xml中添加
Intent intent = getIntent();
String fileType = intent.getType();//文件类型
String filePath = intent.getData().getPath();//文件结对路径
5、待完善
1) 替换功能尚未完成。
2) 细节有待完善,比如退出前判断文件是否已经保存了。
3) 打开文件部分没有路径返回。
4) 文件编码只是简单的处理UTF-8,ANSI,Unicode编码。