Initial commit

This commit is contained in:
linglongxin24
2016-06-14 13:49:26 +08:00
commit ceed245fb3
154 changed files with 16198 additions and 0 deletions

2
library/FilePicker/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/build
/*.iml

View File

@@ -0,0 +1,11 @@
apply plugin: 'com.android.library'
ext {
isLibrary = true
pomArtifactId = "FilePicker"
pomDescription = "file picker for android"
}
dependencies {
compile project(":library:Common")
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.qqtheme.framework.filepicker">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>

View File

@@ -0,0 +1,225 @@
package cn.qqtheme.framework.adapter;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.File;
import java.util.ArrayList;
import cn.qqtheme.framework.entity.FileItem;
import cn.qqtheme.framework.filepicker.R;
import cn.qqtheme.framework.util.CompatUtils;
import cn.qqtheme.framework.util.ConvertUtils;
import cn.qqtheme.framework.util.FileUtils;
import cn.qqtheme.framework.util.LogUtils;
/**
* The type File adapter.
*/
public class FileAdapter extends BaseAdapter {
/**
* The constant DIR_ROOT.
*/
public static final String DIR_ROOT = "..";
/**
* The constant DIR_PARENT.
*/
public static final String DIR_PARENT = "";
private Context context;
private ArrayList<FileItem> data = new ArrayList<FileItem>();
private String rootPath = null;
private String currentPath = null;
private String[] allowExtensions = null;//允许的扩展名
private boolean onlyListDir = false;//是否仅仅读取目录
private boolean showHomeDir = false;//是否显示返回主目录
private boolean showUpDir = true;//是否显示返回上一级
private boolean showHideDir = true;//是否显示隐藏的目录(以“.”开头)
private int homeIcon = R.drawable.file_picker_home;
private int upIcon = R.drawable.file_picker_updir;
private int folderIcon = R.drawable.file_picker_folder;
private int fileIcon = R.drawable.file_picker_file;
/**
* Instantiates a new File adapter.
*
* @param context the context
*/
public FileAdapter(Context context) {
this.context = context;
}
/**
* Gets current path.
*
* @return the current path
*/
public String getCurrentPath() {
return currentPath;
}
/**
* Sets allow extensions.
*
* @param allowExtensions the allow extensions
*/
public void setAllowExtensions(String[] allowExtensions) {
this.allowExtensions = allowExtensions;
}
/**
* Sets only list dir.
*
* @param onlyListDir the only list dir
*/
public void setOnlyListDir(boolean onlyListDir) {
this.onlyListDir = onlyListDir;
}
/**
* Sets show home dir.
*
* @param showHomeDir the show home dir
*/
public void setShowHomeDir(boolean showHomeDir) {
this.showHomeDir = showHomeDir;
}
/**
* Sets show up dir.
*
* @param showUpDir the show up dir
*/
public void setShowUpDir(boolean showUpDir) {
this.showUpDir = showUpDir;
}
/**
* Sets show hide dir.
*
* @param showHideDir the show hide dir
*/
public void setShowHideDir(boolean showHideDir) {
this.showHideDir = showHideDir;
}
/**
* Load data array list.
*
* @param path the path
*/
public void loadData(String path) {
if (path == null) {
LogUtils.warn("current directory is null");
return;
}
ArrayList<FileItem> datas = new ArrayList<FileItem>();
if (rootPath == null) {
rootPath = path;
}
LogUtils.debug("current directory path: " + path);
currentPath = path;
if (showHomeDir) {
//添加“返回主目录”
FileItem fileRoot = new FileItem();
fileRoot.setDirectory(true);
fileRoot.setIcon(homeIcon);
fileRoot.setName(DIR_ROOT);
fileRoot.setSize(0);
fileRoot.setPath(rootPath);
datas.add(fileRoot);
}
if (showUpDir && !path.equals("/")) {
//添加“返回上一级目录”
FileItem fileParent = new FileItem();
fileParent.setDirectory(true);
fileParent.setIcon(upIcon);
fileParent.setName(DIR_PARENT);
fileParent.setSize(0);
fileParent.setPath(new File(path).getParent());
datas.add(fileParent);
}
File[] files;
if (allowExtensions == null) {
if (onlyListDir) {
files = FileUtils.listDirs(currentPath);
} else {
files = FileUtils.listDirsAndFiles(currentPath);
}
} else {
if (onlyListDir) {
files = FileUtils.listDirs(currentPath, allowExtensions);
} else {
files = FileUtils.listDirsAndFiles(currentPath, allowExtensions);
}
}
if (files != null) {
for (File file : files) {
if (!showHideDir && file.getName().startsWith(".")) {
continue;
}
FileItem fileItem = new FileItem();
boolean isDirectory = file.isDirectory();
fileItem.setDirectory(isDirectory);
if (isDirectory) {
fileItem.setIcon(folderIcon);
fileItem.setSize(0);
} else {
fileItem.setIcon(fileIcon);
fileItem.setSize(file.length());
}
fileItem.setName(file.getName());
fileItem.setPath(file.getAbsolutePath());
datas.add(fileItem);
}
}
data.clear();
data.addAll(datas);
notifyDataSetChanged();
}
@Override
public int getCount() {
return data.size();
}
@Override
public FileItem getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(android.R.layout.activity_list_item, null);
CompatUtils.setBackground(convertView, ConvertUtils.toStateListDrawable(Color.WHITE, Color.LTGRAY));
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(android.R.id.icon);
holder.textView = (TextView) convertView.findViewById(android.R.id.text1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
FileItem item = data.get(position);
holder.imageView.setImageResource(item.getIcon());
holder.textView.setText(item.getName());
return convertView;
}
private class ViewHolder {
ImageView imageView;
TextView textView;
}
}

View File

@@ -0,0 +1,106 @@
package cn.qqtheme.framework.entity;
/**
* 文件项信息
*
* @author 李玉江[QQ :1032694760]
* @version 2014 -05-23 18:02
*/
public class FileItem {
private int icon;
private String name;
private String path = "/";
private long size = 0;
private boolean isDirectory = false;
/**
* Sets icon.
*
* @param icon the icon
*/
public void setIcon(int icon) {
this.icon = icon;
}
/**
* Gets icon.
*
* @return the icon
*/
public int getIcon() {
return icon;
}
/**
* Gets name.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Sets name.
*
* @param name the name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets path.
*
* @return the path
*/
public String getPath() {
return path;
}
/**
* Sets path.
*
* @param path the path
*/
public void setPath(String path) {
this.path = path;
}
/**
* Gets size.
*
* @return the size
*/
public long getSize() {
return size;
}
/**
* Sets size.
*
* @param size the size
*/
public void setSize(long size) {
this.size = size;
}
/**
* Is directory boolean.
*
* @return the boolean
*/
public boolean isDirectory() {
return isDirectory;
}
/**
* Sets directory.
*
* @param isDirectory the is directory
*/
public void setDirectory(boolean isDirectory) {
this.isDirectory = isDirectory;
}
}

View File

@@ -0,0 +1,241 @@
package cn.qqtheme.framework.picker;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import cn.qqtheme.framework.adapter.FileAdapter;
import cn.qqtheme.framework.entity.FileItem;
import cn.qqtheme.framework.popup.ConfirmPopup;
import cn.qqtheme.framework.util.ConvertUtils;
import cn.qqtheme.framework.util.LogUtils;
import cn.qqtheme.framework.util.StorageUtils;
import cn.qqtheme.framework.widget.MarqueeTextView;
/**
* 文件目录选择器
*
* @author 李玉江[QQ :1032694760]
* @version 2015 /9/29
*/
public class FilePicker extends ConfirmPopup<LinearLayout> implements AdapterView.OnItemClickListener {
/**
* Directory mode.
*/
public static final int DIRECTORY = 0;
/**
* File mode.
*/
public static final int FILE = 1;
private String initPath;
private FileAdapter adapter;
private MarqueeTextView textView;
private OnFilePickListener onFilePickListener;
private int mode;
@IntDef(flag = false, value = {DIRECTORY, FILE})
@Retention(RetentionPolicy.SOURCE)
public @interface Mode {
}
/**
* Instantiates a new File picker.
*
* @param activity the activity
* @param mode data mode
* @see #FILE #FILE#FILE
* @see #DIRECTORY #DIRECTORY#DIRECTORY
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@RequiresPermission(anyOf = {Manifest.permission.READ_EXTERNAL_STORAGE})
public FilePicker(Activity activity, @Mode int mode) {
super(activity);
setHalfScreen(true);
this.initPath = StorageUtils.getRootPath(activity);
this.mode = mode;
this.adapter = new FileAdapter(activity);
adapter.setOnlyListDir(mode == DIRECTORY);
}
@Override
@NonNull
protected LinearLayout makeCenterView() {
LinearLayout rootLayout = new LinearLayout(activity);
rootLayout.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
rootLayout.setBackgroundColor(Color.WHITE);
rootLayout.setOrientation(LinearLayout.VERTICAL);
ListView listView = new ListView(activity);
listView.setBackgroundColor(Color.WHITE);
listView.setDivider(new ColorDrawable(0xFFDDDDDD));
listView.setDividerHeight(1);
listView.setCacheColorHint(Color.TRANSPARENT);
listView.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
rootLayout.addView(listView);
return rootLayout;
}
@Nullable
@Override
protected View makeFooterView() {
textView = new MarqueeTextView(activity);
textView.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
textView.setTextColor(Color.BLACK);
textView.setGravity(Gravity.CENTER_VERTICAL);
int padding = ConvertUtils.toPx(activity, 10);
textView.setPadding(padding, padding, padding, padding);
return textView;
}
/**
* Sets root path.
*
* @param initPath the init path
*/
public void setRootPath(String initPath) {
this.initPath = initPath;
}
/**
* Sets allow extensions.
*
* @param allowExtensions the allow extensions
*/
public void setAllowExtensions(String[] allowExtensions) {
adapter.setAllowExtensions(allowExtensions);
}
/**
* Sets show up dir.
*
* @param showUpDir the show up dir
*/
public void setShowUpDir(boolean showUpDir) {
adapter.setShowUpDir(showUpDir);
}
/**
* Sets show home dir.
*
* @param showHomeDir the show home dir
*/
public void setShowHomeDir(boolean showHomeDir) {
adapter.setShowHomeDir(showHomeDir);
}
/**
* Sets show hide dir.
*
* @param showHideDir the show hide dir
*/
public void setShowHideDir(boolean showHideDir) {
adapter.setShowHideDir(showHideDir);
}
@Override
protected void setContentViewBefore() {
boolean isPickFile = mode == FILE;
setCancelVisible(!isPickFile);
setSubmitText(isPickFile ? "取消" : "确定");
}
@Override
protected void setContentViewAfter(View contentView) {
refreshCurrentDirPath(initPath);
}
@Override
protected void onSubmit() {
if (mode == FILE) {
LogUtils.debug("已放弃选择!");
} else {
String currentPath = adapter.getCurrentPath();
LogUtils.debug("已选择目录:" + currentPath);
if (onFilePickListener != null) {
onFilePickListener.onFilePicked(currentPath);
}
}
}
/**
* Gets current path.
*
* @return the current path
*/
public String getCurrentPath() {
return adapter.getCurrentPath();
}
/**
* 响应选择器的列表项点击事件
*/
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
FileItem fileItem = adapter.getItem(position);
if (fileItem.isDirectory()) {
refreshCurrentDirPath(fileItem.getPath());
} else {
String clickPath = fileItem.getPath();
if (mode == DIRECTORY) {
LogUtils.debug("选择的不是有效的目录: " + clickPath);
} else {
dismiss();
LogUtils.debug("已选择文件:" + clickPath);
if (onFilePickListener != null) {
onFilePickListener.onFilePicked(clickPath);
}
}
}
}
private void refreshCurrentDirPath(String currentPath) {
if (currentPath.equals("/")) {
textView.setText("根目录");
} else {
textView.setText(currentPath);
}
adapter.loadData(currentPath);
}
/**
* Sets on file pick listener.
*
* @param listener the listener
*/
public void setOnFilePickListener(OnFilePickListener listener) {
this.onFilePickListener = listener;
}
/**
* The interface On file pick listener.
*/
public interface OnFilePickListener {
/**
* On file picked.
*
* @param currentPath the current path
*/
void onFilePicked(String currentPath);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,224 @@
package cn.qqtheme.framework.util;
import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;
import java.io.File;
import java.io.IOException;
/**
* 存储设备工具类
*
* @author 李玉江[QQ :1023694760]
* @version 2013 -11-2
*/
public final class StorageUtils {
/**
* 判断外置存储是否可用
*
* @return the boolean
*/
public static boolean externalMounted() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
return true;
}
LogUtils.warn("external storage unmounted");
return false;
}
/**
* 返回以“/”结尾的外置存储根目录,可选若外置存储不可用则是否使用内部存储
*
* @param context the context
* @param onlyExternalStorage the only external storage
* @param subdir the subdir
* @return 诸如 /mnt/sdcard/subdir
*/
public static String getRootPath(Context context, boolean onlyExternalStorage, String subdir) {
File file;
if (externalMounted()) {
file = Environment.getExternalStorageDirectory();
} else {
if (onlyExternalStorage) {
file = new File("/");
} else {
file = context.getFilesDir();
}
}
if (!TextUtils.isEmpty(subdir)) {
file = new File(file, subdir);
//noinspection ResultOfMethodCallIgnored
file.mkdirs();
}
String path = "/";
if (file != null) {
path = FileUtils.separator(file.getAbsolutePath());
}
LogUtils.debug("storage root path: " + path);
return path;
}
/**
* 返回以“/”结尾的外置存储根目录,可选若外置存储不可用则是否使用内部存储
*
* @param context the context
* @param subdir the subdir
* @return 诸如 /mnt/sdcard/
*/
public static String getRootPath(Context context, String subdir) {
return getRootPath(context, false, subdir);
}
/**
* 返回以“/”结尾的外置存储根目录,可选若外置存储不可用则是否使用内部存储
*
* @param context the context
* @param onlyExternalStorage the only external storage
* @return 诸如 /mnt/sdcard/
*/
public static String getRootPath(Context context, boolean onlyExternalStorage) {
return getRootPath(context, onlyExternalStorage, null);
}
/**
* 返回以“/”结尾的外置存储根目录,若外置存储不可用则使用内部存储
*
* @param context the context
* @return 诸如 /mnt/sdcard/
*/
public static String getRootPath(Context context) {
return getRootPath(context, false);
}
/**
* 下载的文件的保存路径,以“/”结尾
*
* @param context the context
* @return 诸如 /mnt/sdcard/Download/
* @throws Exception the exception
*/
public static String getDownloadPath(Context context) throws Exception {
File file;
if (externalMounted()) {
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
} else {
throw new Exception("外置存储不可用!");
}
return FileUtils.separator(file.getAbsolutePath());
}
/**
* 各种类型的文件的专用的保存路径,以“/”结尾
*
* @param context the context
* @param type the type
* @return 诸如 /mnt/sdcard/Android/data/[package]/files/[type]/
*/
public static String getPrivatePath(Context context, String type) {
File file = null;
if (externalMounted()) {
file = context.getExternalFilesDir(type);
}
if (file == null) {
//SD卡不可用或暂时繁忙
if (type == null) {
file = context.getFilesDir();
} else {
file = new File(FileUtils.separator(context.getFilesDir().getAbsolutePath()) + type);
//noinspection ResultOfMethodCallIgnored
file.mkdirs();
}
}
return FileUtils.separator(file.getAbsolutePath());
}
/**
* Gets internal root path.
*
* @param context the context
* @return the internal root path
*/
public static String getInternalRootPath(Context context) {
return FileUtils.separator(context.getFilesDir().getAbsolutePath());
}
/**
* Gets private root path.
*
* @param context the context
* @return the private root path
*/
public static String getPrivateRootPath(Context context) {
return getPrivatePath(context, null);
}
/**
* Gets plugin path.
*
* @param context the context
* @return the plugin path
*/
public static String getPluginPath(Context context) {
return getPrivatePath(context, "plugin");
}
/**
* Gets temporary dir path.
*
* @param context the context
* @return the temporary dir path
*/
public static String getTemporaryDirPath(Context context) {
return getPrivatePath(context, "temporary");
}
/**
* Gets temporary file path.
*
* @param context the context
* @return the temporary file path
*/
public static String getTemporaryFilePath(Context context) {
try {
return File.createTempFile("lyj_", ".tmp", context.getCacheDir()).getAbsolutePath();
} catch (IOException e) {
return getTemporaryDirPath(context) + "lyj.tmp";
}
}
/**
* Gets cache path.
*
* @param context the context
* @param type the type
* @return the cache path
*/
public static String getCachePath(Context context, String type) {
File file;
if (externalMounted()) {
file = context.getExternalCacheDir();
} else {
file = context.getCacheDir();
}
if (type != null) {
file = new File(file, type);
//noinspection ResultOfMethodCallIgnored
file.mkdirs();
}
return FileUtils.separator(file != null ? file.getAbsolutePath() : null);
}
/**
* Gets cache root path.
*
* @param context the context
* @return the cache root path
*/
public static String getCacheRootPath(Context context) {
return getCachePath(context, null);
}
}

View File

@@ -0,0 +1,57 @@
package cn.qqtheme.framework.widget;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.TextView;
/**
* 文本水平自动滚动(从右到左)。
*
* @author 李玉江[QQ :1023694760]
* @version 2013 -1-11
*/
public class MarqueeTextView extends TextView {
/**
* Instantiates a new Marquee text view.
*
* @param context the context
*/
public MarqueeTextView(Context context) {
this(context, null);
}
/**
* Instantiates a new Marquee text view.
*
* @param context the context
* @param attr the attr
*/
public MarqueeTextView(Context context, AttributeSet attr) {
super(context, attr);
setEllipsize(TextUtils.TruncateAt.MARQUEE);
setMarqueeRepeatLimit(-1);
setSingleLine(true);
setHorizontallyScrolling(true);
setClickable(true);
setFocusable(true);
setFocusableInTouchMode(true);
setGravity(Gravity.CENTER);
}
/**
* 必须已获取到焦点,才能即显滚动
*/
@Override
public boolean isFocused() {
return true;
}
@Override
public boolean isPressed() {
return true;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B