AndroidTXT阅读器的实现(—)扫描sd卡或选择文件路径添加文件到listview及listview的多选删除
来源:互联网 发布:文件隐藏软件 编辑:程序博客网 时间:2024/06/07 22:52
不知怎么突然有了想写一个txt阅读器的想法 ……目前只实现了一小部分功能,并且参考了网上很多大神的代码,受益匪浅!!~
目前实现的功能:
1.(1)首次打开阅读器时,会弹出选择对话框,可以选择扫描sd卡方式,扫描出sd卡上的所有txt文件并进行简单的筛选(>50KB)之后,得到的文件将被显示在ListView中;
(2)若选择了通过路径添加,则会弹出路径选择的Activity,点击确定后选择的txt文件将会出现在ListView的最后;
(3)若选择了稍后手动添加,则稍候可点击界面右上角加号弹出该选择对话框。
2.长按ListView中的item,则会进入多选删除模式。
嗯哼……开始贴代码了……
主activity的布局文件就不贴了 。。一个ListView。。。一个listitem。。。贴一下menu:book_list.xml
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_addingbooks" android:icon="@android:drawable/ic_menu_add" android:orderInCategory="500" android:showAsAction="ifRoom" android:title="添加书籍"/></menu>
实现右上角的加号,点击弹出添加书籍对话框功能。
然后是BookListActivity.class
package com.ldgforever.jianreader;import android.app.*;import android.content.DialogInterface;import android.content.Intent;import android.os.*;import android.util.Log;import android.view.*;import android.widget.ListView;import android.widget.Toast;import android.widget.AbsListView.MultiChoiceModeListener;import com.ldgforever.jianreader.R;import com.ldgforever.savedata.savedataListMap;import java.io.File;import java.util.*;public class BookListActivity extends Activity {private static List<String> file_name;private static List<String> file_txt_path;private MyBookAdapter adapter;private File file;private List<Map<String, String>> listItems;private MultiModeCallback mCallback;private String mExternalStoragePath;private Handler mHandler;private ListView mListView;private ProgressDialog mProgressDialog;/** * 接收返回的路径 */@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {Log.d("com.ldgforever.jianreader", "receivingPath");if (data != null) {Log.d("com.ldgforever.jianreader", "onActivityResult");String mPath = data.getStringExtra("file");File pathFile = new File(mPath);Map<String, String> pathMap = new HashMap<String, String>();if (pathFile.exists()) {if (pathFile.getName().endsWith(".txt")) {pathMap.put("Name", pathFile.getName());pathMap.put("Path", pathFile.getPath());listItems.add(pathMap);savedataListMap.saveInfo(BookListActivity.this, "ListMap", listItems);ShowTxtFilesInList(listItems);} else {Toast.makeText(BookListActivity.this, "请选择一个txt文件!", 0).show();;}}}}@Overrideprotected void onCreate(Bundle bundle) {super.onCreate(bundle);setContentView(R.layout.activity_book_list);mProgressDialog = new ProgressDialog(BookListActivity.this);mProgressDialog.setCancelable(false);mProgressDialog.setMessage("正在搜索书籍,请稍候 ……");mExternalStoragePath = Environment.getExternalStorageDirectory().toString();file = new File(mExternalStoragePath);file_name = new ArrayList<String>();file_txt_path = new ArrayList<String>();listItems = new ArrayList<Map<String, String>>();listItems = savedataListMap.getInfo(BookListActivity.this, "ListMap");if (listItems.isEmpty()) {BookAddingDialog();} else {ShowTxtFilesInList(listItems);}mHandler = new Handler() {public void handleMessage(Message message) {switch (message.what) {case 11:ShowTxtFilesInList(listItems);savedataListMap.saveInfo(BookListActivity.this, "ListMap", listItems);if (mProgressDialog.isShowing()) {mProgressDialog.dismiss();return;}break;case 12:ShowTxtFilesInList(listItems);savedataListMap.saveInfo(BookListActivity.this, "ListMap", listItems);if (mProgressDialog.isShowing()) {mProgressDialog.dismiss();return;}break;default:break;}return;}};}/** * 书籍添加对话框 */private void BookAddingDialog() {android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this);builder.setTitle("请选择添加书籍的方式");builder.setPositiveButton("扫描SDCard添加", new android.content.DialogInterface.OnClickListener() {public void onClick(DialogInterface dialoginterface, int i) {listItems = new ArrayList<Map<String, String>>();mProgressDialog.show();new Thread() {public void run() {listFileTxt(file);mHandler.sendEmptyMessage(12);}}.start();}});builder.setNegativeButton("选择路径添加", new android.content.DialogInterface.OnClickListener() {public void onClick(DialogInterface dialoginterface, int i) {Intent intent = new Intent(BookListActivity.this, MyFileManager.class);startActivityForResult(intent, 2);}});builder.setNeutralButton("稍后手动添加", new android.content.DialogInterface.OnClickListener() {public void onClick(DialogInterface dialoginterface, int i) {dialoginterface.dismiss();}});builder.create().show();}/** * 将保存在List<Map<String,String>>中的书籍信息显示到ListView中 * @param listItems */private void ShowTxtFilesInList(List<Map<String, String>> listItems) {if (file_name != null) {for (int i = 0; i < file_name.size(); i++) {HashMap<String, String> hashmap = new HashMap<String, String>();hashmap.put("Name", (String) file_name.get(i));hashmap.put("Path", (String) file_txt_path.get(i));listItems.add(hashmap);}adapter = new MyBookAdapter(this, listItems);mCallback = new MultiModeCallback();mListView = (ListView) findViewById(R.id.booklist);mListView.setChoiceMode(3); // MultimListView.setMultiChoiceModeListener(mCallback);mListView.setAdapter(adapter);} else {failAddingDialog();return;}}/** * 添加书籍失败对话框 */private void failAddingDialog() {android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this);builder.setTitle("添加书籍失败");builder.setPositiveButton("确定", new android.content.DialogInterface.OnClickListener() {public void onClick(DialogInterface dialoginterface, int i) {dialoginterface.dismiss();}});}/** * 递归查找SD卡上所有书籍 * @param file */public static void listFileTxt(File file) {File[] files = file.listFiles();try {for (File f : files) {if (!f.isDirectory()) {if (f.getName().endsWith(".txt")) {long size = f.length();if (size > 50 * 1024) {file_name.add(f.getName());file_txt_path.add(f.getAbsolutePath());}}} else if (f.isDirectory()) {listFileTxt(f);}}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}public boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.book_list, menu);return super.onCreateOptionsMenu(menu);}public boolean onOptionsItemSelected(MenuItem menuitem) {switch (menuitem.getItemId()) {case R.id.action_addingbooks:BookAddingDialog();break;default:break;}return true;}private class MultiModeCallback implements MultiChoiceModeListener {public boolean onActionItemClicked(ActionMode actionmode, MenuItem menuitem) {switch (menuitem.getItemId()) {case R.id.menu_delete:adapter.deleteSeletcedItems();adapter.notifyDataSetChanged();actionmode.finish();return true;default:return false;}}public boolean onCreateActionMode(ActionMode actionmode, Menu menu) {actionmode.getMenuInflater().inflate(R.menu.book_actionmenu, menu);adapter.setItemMultiCheckable(true);adapter.notifyDataSetChanged();return true;}public void onDestroyActionMode(ActionMode actionmode) {savedataListMap.saveInfo(BookListActivity.this, "ListMap", listItems);adapter.setItemMultiCheckable(false);adapter.clearSeletedItems();adapter.notifyDataSetChanged();}public void onItemCheckedStateChanged(ActionMode actionmode, int i, long l, boolean flag) {if (flag)adapter.addSelectedItem(i);elseadapter.cancelSelectedItem(i);adapter.notifyDataSetChanged();actionmode.invalidate();}public boolean onPrepareActionMode(ActionMode actionmode, Menu menu) {return false;}}}
程序里有一定的注释0-0,直接看比较清晰。查找txt文件用的是递归查找文件名末尾为".txt"的文件,如果满足条件就添加到Map<String,String>里。这里还自定义了一个Adapter用以将txt文件更新到ListView上并且应用了ActionMode实现了ListView的多选和删除功能。关于ActionMode的使用参考了以下两篇文章,感谢!
1.http://blog.csdn.net/xyz_lmn/article/details/12754785
2.http://blog.csdn.net/ghost_programmer/article/details/46827933 (强推)
然后就是点击通过路径添加之后通过startForResult打开路径添加的Activity
嚄……贴一下actionmode的menu,里面只有一个删除的按钮
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/menu_delete" android:icon="@android:drawable/ic_menu_delete" android:showAsAction="ifRoom" android:title="删除"/></menu>
贴一下自定义的BookAdapter,删除添加item的方法也写在了里面
package com.ldgforever.jianreader;import android.content.Context;import android.view.*;import android.widget.*;import java.util.*;import com.ldgforever.jianreader.R;public class MyBookAdapter extends BaseAdapter {private List<Map<String, String>> listItems;private static List<Map<String, String>> isSelected;private boolean itemMultiCheckable;private Context mContext;private ViewHolder mViewHolder;static class ViewHolder {public TextView mBookName;public CheckBox mCheckBox;}public MyBookAdapter(Context context, List<Map<String, String>> listItems) {this.mContext = context;this.listItems = listItems;isSelected = new ArrayList<Map<String, String>>();}@Overridepublic long getItemId(int position) {return position;}@Overridepublic int getCount() {return listItems.size();}@Overridepublic Object getItem(int i) {return listItems.get(i);}@Overridepublic View getView(int i, View view, ViewGroup viewgroup) {mViewHolder = new ViewHolder();if (view == null) {view = LayoutInflater.from(mContext).inflate(R.layout.booklist_item, null);mViewHolder.mBookName = (TextView) view.findViewById(R.id.book_name);mViewHolder.mCheckBox = (CheckBox) view.findViewById(R.id.mCheckBox);view.setTag(mViewHolder);} else {mViewHolder = (ViewHolder) view.getTag();}if (itemMultiCheckable) {mViewHolder.mCheckBox.setVisibility(View.VISIBLE);if (isSelected.contains(listItems.get(i))) {mViewHolder.mCheckBox.setChecked(true);} else {mViewHolder.mCheckBox.setChecked(false);}} else {mViewHolder.mCheckBox.setVisibility(View.GONE);}mViewHolder.mBookName.setText(listItems.get(i).get("Name"));return view;}public void addSelectedItem(int i) {isSelected.add(listItems.get(i));}public void cancelSelectedItem(int i) {isSelected.remove(listItems.get(i));}public void clearSeletedItems() {isSelected = new ArrayList<Map<String, String>>();}public void deleteSeletcedItems() {for (Map<String, String> map : isSelected) {listItems.remove(map);}}public void setItemMultiCheckable(boolean flag) {itemMultiCheckable = flag;}}
package com.ldgforever.jianreader;import java.io.Serializable;import java.util.List;import java.util.Map;public class SeriallizableList implements Serializable {private List<Map<String, String>> listItems;public SeriallizableList() {}public List<Map<String, String>> getListItems() {return listItems;}public void setListItems(List<Map<String, String>> list) {listItems = list;}}
然后0.0就到了选择路径添加的部分……首先来看一下布局文件
一个用来显示当前目录路径的TextView,一个ListView列出可供选择的文件,线性布局的最下方是确定和取消两个按钮。这里还应用了Selector来改变点击ListView的item时的背景颜色,为了某种程度上的美观……?通过android:listSelector = "@drawable/mfilelist_view"设置
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF" android:orientation="vertical" > <TextView android:id="@+id/tv_path" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="5px" android:textColor="#436EEE" android:textSize="20sp" > </TextView> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="9" android:listSelector="@drawable/mfilelist_view"> </ListView> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#FFFFFF" android:orientation="horizontal" > <Button android:id="@+id/btn_yes" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="6dp" android:layout_weight="1" android:background="#436EEE" android:text="确定" android:textColor="#FFFFFF" /> <Button android:id="@+id/btn_cancel" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="6dp" android:layout_weight="1" android:background="#436EEE" android:text="取消" android:textColor="#FFFFFF" /> </LinearLayout></LinearLayout>
mfilelist_view.xml如下
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_selected="true" android:drawable="@color/lightyellow" /> <item android:state_focused="true" android:drawable="@color/lightyellow" /> <item android:state_pressed="true" android:drawable="@color/lightyellow" /> </selector>
及其应用的color.xml(values文件夹下)
<?xml version="1.0" encoding="utf-8"?><resources> <color name="white">#ffffff</color> <color name="black">#000000</color> <color name="lightyellow">#FFEBCD</color></resources>
list_item懒得贴了,没有什么图标啥的就是一个光秃秃的TextView。
自定义的Adapter如下
package com.ldgforever.jianreader;import java.io.File;import java.util.List;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;public class MyFileAdapter extends BaseAdapter {private LayoutInflater mInflater;private List<String> items;private List<String> paths;public MyFileAdapter(Context context, List<String> items, List<String> paths) {mInflater = LayoutInflater.from(context);this.items = items;this.paths = paths;}public int getCount() {return items.size();}public Object getItem(int position) {return items.get(position);}public long getItemId(int position) {return position;}public View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = mInflater.inflate(R.layout.filelist_item, null);holder = new ViewHolder();holder.mFileTextView = (TextView) convertView.findViewById(R.id.list_text);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}File f = new File(paths.get(position).toString());if (items.get(position).toString().equals("b1")) {holder.mFileTextView.setText("返回根目录..");} else if (items.get(position).toString().equals("b2")) {holder.mFileTextView.setText("返回上一层..");} else {if (f.isDirectory()) {holder.mFileTextView.setText("+ "+f.getName());} else {holder.mFileTextView.setText(f.getName());}}return convertView;}private class ViewHolder {TextView mFileTextView;}}
package com.ldgforever.jianreader;import java.io.File;import java.util.ArrayList;import java.util.List;import android.app.ListActivity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;public class MyFileManager extends ListActivity {private List<String> items = null;private List<String> paths = null;private String rootPath = "/";private String curPath = "/";private TextView mPath;private MyFileAdapter adapter;private boolean mItemFlag = false;@Overrideprotected void onCreate(Bundle bundle) {super.onCreate(bundle);setContentView(R.layout.activity_fileselect_list);mPath = (TextView) findViewById(R.id.tv_path);Button buttonConfirm = (Button) findViewById(R.id.btn_yes);buttonConfirm.setOnClickListener(new OnClickListener() {public void onClick(View v) {if (mItemFlag) {Intent data = new Intent(MyFileManager.this, BookListActivity.class);data.putExtra("file", curPath);Log.d("com.ldgforever.jianreader", curPath);setResult(2, data);finish();} else {Toast.makeText(MyFileManager.this, "请选择一个txt文件!", 0).show();}}});Button buttonCancle = (Button) findViewById(R.id.btn_cancel);buttonCancle.setOnClickListener(new OnClickListener() {public void onClick(View v) {finish();}});getFileDir(rootPath);}/** * 如果文件是目录,则将目录下的文件显示在listview中 * * @param filePath */private void getFileDir(String filePath) {mPath.setText(filePath);items = new ArrayList<String>();paths = new ArrayList<String>();File f = new File(filePath);adapter = new MyFileAdapter(this, items, paths);if (f.isDirectory()) {File[] files = f.listFiles();if (!filePath.equals(rootPath)) {items.add("b1");paths.add(rootPath);items.add("b2");paths.add(f.getParent());}if (files != null) {for (int i = 0; i < files.length; i++) {File file = files[i];items.add(file.getName());paths.add(file.getPath());}}}setListAdapter(adapter);}@Overrideprotected void onListItemClick(ListView l, View v, int position, long id) {if (!mItemFlag) {v.setBackgroundColor(getResources().getColor(R.color.lightyellow));mItemFlag = true;} else {v.setBackgroundColor(getResources().getColor(R.color.white));mItemFlag = false;}File file = new File(paths.get(position));if (file != null) {if (file.isDirectory()) {curPath = paths.get(position);getFileDir(paths.get(position));} else {curPath = paths.get(position);}}}}
- AndroidTXT阅读器的实现(—)扫描sd卡或选择文件路径添加文件到listview及listview的多选删除
- Android 选择文件对话框并将选择内容添加至ListView,并实现listview的删除与事件触发
- android ProgressBar实现扫描SD卡文件 + SimpleAdapter绑定ListView
- AndroidTXT阅读器的实现(二)ViewPager欢迎界面和SplashActivity
- 【Java】拷贝assets的文件到SD卡指定路径
- 关于ListView或控件选择循环切换的实现方法
- 随便做着玩-实现删除选择ListView的条目
- Android 的ListView操作实例,文件管理器SD卡的读取操作
- Java 多文件上传存储到不同的路径及某上传框中未选择上传文件的处理方法
- android 扫描文件(sdcard添加新的音乐文件时候后,可扫描到)
- android dialog中嵌套ListView实现对ListView的添加、删除操作
- 基于ListView的滑动删除、添加、修改
- android 模拟器添加文件到sd卡
- 遍历SD卡及删除、重命名文件
- 调用系统控件,打开选择文件或路径的对话框
- VC选择 文件 或 目录 路径的代码
- 安卓——ListView的动态添加与删除
- 动态添加和删除文件选择框及脚本的兼容性问题。
- HTTP Message Length
- <jsp:include page=""/>与iframe
- js中关于时间的一些函数
- 分割单词
- spring mvc 小记(六):关于MySql优化
- AndroidTXT阅读器的实现(—)扫描sd卡或选择文件路径添加文件到listview及listview的多选删除
- 矩阵链乘 动态规划
- HiveSQL-datediff函数
- c++第三周初
- View 触摸事件分发拦截机制(一)
- DEV 控件----GridControl
- solr-6.1.0源码分析---4
- 软件测试与软件测试用例
- spring mvc 时间类型传值问题