copy a part related to file picking into a separate module
@ -1,174 +0,0 @@
|
|||||||
package com.simplemobiletools.filemanager;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Point;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.Display;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.simplemobiletools.filemanager.models.FileDirItem;
|
|
||||||
|
|
||||||
public class Breadcrumbs extends LinearLayout implements View.OnClickListener {
|
|
||||||
private int mDeviceWidth;
|
|
||||||
|
|
||||||
private LayoutInflater mInflater;
|
|
||||||
private BreadcrumbsListener mListener;
|
|
||||||
|
|
||||||
public Breadcrumbs(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(Context context) {
|
|
||||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
final Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
|
||||||
final Point deviceDisplay = new Point();
|
|
||||||
display.getSize(deviceDisplay);
|
|
||||||
mDeviceWidth = deviceDisplay.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setListener(BreadcrumbsListener listener) {
|
|
||||||
mListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
|
||||||
final int paddingTop = getPaddingTop();
|
|
||||||
final int paddingLeft = getPaddingLeft();
|
|
||||||
final int paddingRight = getPaddingRight();
|
|
||||||
final int childRight = getMeasuredWidth() - paddingRight;
|
|
||||||
final int childBottom = getMeasuredHeight() - getPaddingBottom();
|
|
||||||
final int childHeight = childBottom - paddingTop;
|
|
||||||
|
|
||||||
final int usableWidth = mDeviceWidth - paddingLeft - paddingRight;
|
|
||||||
int maxHeight = 0;
|
|
||||||
int curWidth;
|
|
||||||
int curHeight;
|
|
||||||
int curLeft = paddingLeft;
|
|
||||||
int curTop = paddingTop;
|
|
||||||
|
|
||||||
final int cnt = getChildCount();
|
|
||||||
for (int i = 0; i < cnt; i++) {
|
|
||||||
final View child = getChildAt(i);
|
|
||||||
|
|
||||||
child.measure(MeasureSpec.makeMeasureSpec(usableWidth, MeasureSpec.AT_MOST),
|
|
||||||
MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST));
|
|
||||||
curWidth = child.getMeasuredWidth();
|
|
||||||
curHeight = child.getMeasuredHeight();
|
|
||||||
|
|
||||||
if (curLeft + curWidth >= childRight) {
|
|
||||||
curLeft = paddingLeft;
|
|
||||||
curTop += maxHeight;
|
|
||||||
maxHeight = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
child.layout(curLeft, curTop, curLeft + curWidth, curTop + curHeight);
|
|
||||||
if (maxHeight < curHeight)
|
|
||||||
maxHeight = curHeight;
|
|
||||||
|
|
||||||
curLeft += curWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
||||||
final int usableWidth = mDeviceWidth - getPaddingLeft() - getPaddingRight();
|
|
||||||
int width = 0;
|
|
||||||
int rowHeight = 0;
|
|
||||||
int lines = 1;
|
|
||||||
|
|
||||||
final int cnt = getChildCount();
|
|
||||||
for (int i = 0; i < cnt; i++) {
|
|
||||||
final View child = getChildAt(i);
|
|
||||||
measureChild(child, widthMeasureSpec, heightMeasureSpec);
|
|
||||||
width += child.getMeasuredWidth();
|
|
||||||
rowHeight = child.getMeasuredHeight();
|
|
||||||
|
|
||||||
if (width / usableWidth > 0) {
|
|
||||||
lines++;
|
|
||||||
width = child.getMeasuredWidth();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
|
|
||||||
final int calculatedHeight = getPaddingTop() + getPaddingBottom() + (rowHeight * lines);
|
|
||||||
setMeasuredDimension(parentWidth, calculatedHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInitialBreadcrumb(String fullPath) {
|
|
||||||
final boolean showFullPath = Config.newInstance(getContext()).getShowFullPath();
|
|
||||||
final String basePath = Environment.getExternalStorageDirectory().toString();
|
|
||||||
String tempPath = fullPath;
|
|
||||||
String currPath = basePath;
|
|
||||||
if (!showFullPath) {
|
|
||||||
tempPath = fullPath.replace(basePath, getContext().getString(R.string.initial_breadcrumb) + "/");
|
|
||||||
} else {
|
|
||||||
currPath = "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
removeAllViewsInLayout();
|
|
||||||
final String[] dirs = tempPath.split("/");
|
|
||||||
for (int i = 0; i < dirs.length; i++) {
|
|
||||||
final String dir = dirs[i];
|
|
||||||
if (i > 0) {
|
|
||||||
currPath += dir + "/";
|
|
||||||
} else if (showFullPath) {
|
|
||||||
addRootFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
final FileDirItem item = new FileDirItem(currPath, dir, true, 0, 0);
|
|
||||||
addBreadcrumb(item, i > 0 || showFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dirs.length == 0 && showFullPath) {
|
|
||||||
addRootFolder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addBreadcrumb(FileDirItem item, boolean addPrefix) {
|
|
||||||
final View view = mInflater.inflate(R.layout.breadcrumb_item, null, false);
|
|
||||||
final TextView textView = (TextView) view.findViewById(R.id.breadcrumb_text);
|
|
||||||
|
|
||||||
String textToAdd = item.getName();
|
|
||||||
if (addPrefix)
|
|
||||||
textToAdd = " -> " + textToAdd;
|
|
||||||
textView.setText(textToAdd);
|
|
||||||
addView(view);
|
|
||||||
view.setOnClickListener(this);
|
|
||||||
|
|
||||||
view.setTag(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeBreadcrumb() {
|
|
||||||
removeView(getChildAt(getChildCount() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addRootFolder() {
|
|
||||||
final FileDirItem item = new FileDirItem("/", " / ", true, 0, 0);
|
|
||||||
addBreadcrumb(item, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
final int cnt = getChildCount();
|
|
||||||
for (int i = 0; i < cnt; i++) {
|
|
||||||
if (getChildAt(i) != null && getChildAt(i).equals(v)) {
|
|
||||||
if (mListener != null) {
|
|
||||||
mListener.breadcrumbClicked(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface BreadcrumbsListener {
|
|
||||||
void breadcrumbClicked(int id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,166 @@
|
|||||||
|
package com.simplemobiletools.filemanager
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Point
|
||||||
|
import android.os.Environment
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.simplemobiletools.filemanager.models.FileDirItem
|
||||||
|
|
||||||
|
class Breadcrumbs(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs), View.OnClickListener {
|
||||||
|
private var mDeviceWidth: Int = 0
|
||||||
|
|
||||||
|
private var mInflater: LayoutInflater? = null
|
||||||
|
private var mListener: BreadcrumbsListener? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
init(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun init(context: Context) {
|
||||||
|
mInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||||
|
val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
|
||||||
|
val deviceDisplay = Point()
|
||||||
|
display.getSize(deviceDisplay)
|
||||||
|
mDeviceWidth = deviceDisplay.x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setListener(listener: BreadcrumbsListener) {
|
||||||
|
mListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||||
|
val paddingTop = paddingTop
|
||||||
|
val paddingLeft = paddingLeft
|
||||||
|
val paddingRight = paddingRight
|
||||||
|
val childRight = measuredWidth - paddingRight
|
||||||
|
val childBottom = measuredHeight - paddingBottom
|
||||||
|
val childHeight = childBottom - paddingTop
|
||||||
|
|
||||||
|
val usableWidth = mDeviceWidth - paddingLeft - paddingRight
|
||||||
|
var maxHeight = 0
|
||||||
|
var curWidth: Int
|
||||||
|
var curHeight: Int
|
||||||
|
var curLeft = paddingLeft
|
||||||
|
var curTop = paddingTop
|
||||||
|
|
||||||
|
val cnt = childCount
|
||||||
|
for (i in 0..cnt - 1) {
|
||||||
|
val child = getChildAt(i)
|
||||||
|
|
||||||
|
child.measure(View.MeasureSpec.makeMeasureSpec(usableWidth, View.MeasureSpec.AT_MOST),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(childHeight, View.MeasureSpec.AT_MOST))
|
||||||
|
curWidth = child.measuredWidth
|
||||||
|
curHeight = child.measuredHeight
|
||||||
|
|
||||||
|
if (curLeft + curWidth >= childRight) {
|
||||||
|
curLeft = paddingLeft
|
||||||
|
curTop += maxHeight
|
||||||
|
maxHeight = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
child.layout(curLeft, curTop, curLeft + curWidth, curTop + curHeight)
|
||||||
|
if (maxHeight < curHeight)
|
||||||
|
maxHeight = curHeight
|
||||||
|
|
||||||
|
curLeft += curWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
val usableWidth = mDeviceWidth - paddingLeft - paddingRight
|
||||||
|
var width = 0
|
||||||
|
var rowHeight = 0
|
||||||
|
var lines = 1
|
||||||
|
|
||||||
|
val cnt = childCount
|
||||||
|
for (i in 0..cnt - 1) {
|
||||||
|
val child = getChildAt(i)
|
||||||
|
measureChild(child, widthMeasureSpec, heightMeasureSpec)
|
||||||
|
width += child.measuredWidth
|
||||||
|
rowHeight = child.measuredHeight
|
||||||
|
|
||||||
|
if (width / usableWidth > 0) {
|
||||||
|
lines++
|
||||||
|
width = child.measuredWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val parentWidth = View.MeasureSpec.getSize(widthMeasureSpec)
|
||||||
|
val calculatedHeight = paddingTop + paddingBottom + rowHeight * lines
|
||||||
|
setMeasuredDimension(parentWidth, calculatedHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setInitialBreadcrumb(fullPath: String) {
|
||||||
|
val showFullPath = Config.newInstance(context).showFullPath
|
||||||
|
val basePath = Environment.getExternalStorageDirectory().toString()
|
||||||
|
var tempPath = fullPath
|
||||||
|
var currPath = basePath
|
||||||
|
if (!showFullPath) {
|
||||||
|
tempPath = fullPath.replace(basePath, context.getString(R.string.initial_breadcrumb) + "/")
|
||||||
|
} else {
|
||||||
|
currPath = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAllViewsInLayout()
|
||||||
|
val dirs = tempPath.split("/".toRegex()).dropLastWhile(String::isEmpty).toTypedArray()
|
||||||
|
for (i in dirs.indices) {
|
||||||
|
val dir = dirs[i]
|
||||||
|
if (i > 0) {
|
||||||
|
currPath += dir + "/"
|
||||||
|
} else if (showFullPath) {
|
||||||
|
addRootFolder()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir.isEmpty())
|
||||||
|
continue
|
||||||
|
|
||||||
|
val item = FileDirItem(currPath, dir, true, 0, 0)
|
||||||
|
addBreadcrumb(item, i > 0 || showFullPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirs.size == 0 && showFullPath) {
|
||||||
|
addRootFolder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addBreadcrumb(item: FileDirItem, addPrefix: Boolean) {
|
||||||
|
val view = mInflater!!.inflate(R.layout.breadcrumb_item, null, false)
|
||||||
|
val textView = view.findViewById(R.id.breadcrumb_text) as TextView
|
||||||
|
|
||||||
|
var textToAdd = item.name
|
||||||
|
if (addPrefix)
|
||||||
|
textToAdd = " -> " + textToAdd
|
||||||
|
textView.text = textToAdd
|
||||||
|
addView(view)
|
||||||
|
view.setOnClickListener(this)
|
||||||
|
|
||||||
|
view.tag = item
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeBreadcrumb() {
|
||||||
|
removeView(getChildAt(childCount - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addRootFolder() {
|
||||||
|
val item = FileDirItem("/", " / ", true, 0, 0)
|
||||||
|
addBreadcrumb(item, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
val cnt = childCount
|
||||||
|
for (i in 0..cnt - 1) {
|
||||||
|
if (getChildAt(i) != null && getChildAt(i) == v) {
|
||||||
|
mListener?.breadcrumbClicked(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BreadcrumbsListener {
|
||||||
|
fun breadcrumbClicked(id: Int)
|
||||||
|
}
|
||||||
|
}
|
@ -77,11 +77,11 @@ class SelectFolderDialog : DialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupBreadcrumbs() {
|
private fun setupBreadcrumbs() {
|
||||||
dialog.directory_picker_breadcrumbs.setListener { id ->
|
/*dialog.directory_picker_breadcrumbs.setListener { id ->
|
||||||
val item = dialog.directory_picker_breadcrumbs.getChildAt(id).tag as FileDirItem
|
val item = dialog.directory_picker_breadcrumbs.getChildAt(id).tag as FileDirItem
|
||||||
mPath = item.path
|
mPath = item.path
|
||||||
updateItems()
|
updateItems()
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getItems(path: String): List<FileDirItem> {
|
private fun getItems(path: String): List<FileDirItem> {
|
||||||
@ -99,10 +99,9 @@ class SelectFolderDialog : DialogFragment() {
|
|||||||
|
|
||||||
val curPath = file.absolutePath
|
val curPath = file.absolutePath
|
||||||
val curName = Utils.getFilename(curPath)
|
val curName = Utils.getFilename(curPath)
|
||||||
val children = getChildren(file)
|
|
||||||
val size = file.length()
|
val size = file.length()
|
||||||
|
|
||||||
items.add(FileDirItem(curPath, curName, file.isDirectory, children, size))
|
items.add(FileDirItem(curPath, curName, file.isDirectory, getChildren(file), size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
|
@ -1 +1 @@
|
|||||||
include ':app'
|
include ':app', ':simplefilepicker'
|
||||||
|
47
simplefilepicker/build.gradle
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 24
|
||||||
|
buildToolsVersion "24.0.2"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 16
|
||||||
|
targetSdkVersion 24
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile 'com.android.support:appcompat-v7:24.2.1'
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.0.3'
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
17
simplefilepicker/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in $ANDROID_HOME/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
9
simplefilepicker/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.simplemobiletools.filepicker">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:label="@string/app_name">
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</manifest>
|
@ -0,0 +1,79 @@
|
|||||||
|
package com.simplemobiletools.filepicker.adapters
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
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 com.simplemobiletools.filepicker.R
|
||||||
|
import com.simplemobiletools.filepicker.extensions.formatSize
|
||||||
|
import com.simplemobiletools.filepicker.extensions.getColoredIcon
|
||||||
|
import com.simplemobiletools.filepicker.models.FileDirItem
|
||||||
|
import kotlinx.android.synthetic.main.list_item.view.*
|
||||||
|
|
||||||
|
class ItemsAdapter(context: Context, private val mItems: List<FileDirItem>) : BaseAdapter() {
|
||||||
|
private val mInflater: LayoutInflater
|
||||||
|
private val mFileBmp: Bitmap
|
||||||
|
private val mDirectoryBmp: Bitmap
|
||||||
|
private val mRes: Resources
|
||||||
|
|
||||||
|
init {
|
||||||
|
mInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||||
|
|
||||||
|
mRes = context.resources
|
||||||
|
mDirectoryBmp = mRes.getColoredIcon(R.color.thumbnail_grey, R.mipmap.directory)
|
||||||
|
mFileBmp = mRes.getColoredIcon(R.color.thumbnail_grey, R.mipmap.file)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||||
|
var view = convertView
|
||||||
|
val viewHolder: ViewHolder
|
||||||
|
if (view == null) {
|
||||||
|
view = mInflater.inflate(R.layout.list_item, parent, false)
|
||||||
|
viewHolder = ViewHolder(view)
|
||||||
|
view!!.tag = viewHolder
|
||||||
|
} else {
|
||||||
|
viewHolder = view.tag as ViewHolder
|
||||||
|
}
|
||||||
|
|
||||||
|
val item = mItems[position]
|
||||||
|
viewHolder.name.text = item.name
|
||||||
|
|
||||||
|
if (item.isDirectory) {
|
||||||
|
viewHolder.icon.setImageBitmap(mDirectoryBmp)
|
||||||
|
viewHolder.details.text = getChildrenCnt(item)
|
||||||
|
} else {
|
||||||
|
viewHolder.icon.setImageBitmap(mFileBmp)
|
||||||
|
viewHolder.details.text = item.size.formatSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getChildrenCnt(item: FileDirItem): String {
|
||||||
|
val children = item.children
|
||||||
|
return mRes.getQuantityString(R.plurals.items, children, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCount(): Int {
|
||||||
|
return mItems.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItem(position: Int): Any {
|
||||||
|
return mItems[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemId(position: Int): Long {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ViewHolder(view: View) {
|
||||||
|
val name: TextView = view.item_name
|
||||||
|
val icon: ImageView = view.item_icon
|
||||||
|
val details: TextView = view.item_details
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
package com.simplemobiletools.filepicker.dialogs
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.support.v4.app.DialogFragment
|
||||||
|
import android.support.v7.app.AlertDialog
|
||||||
|
import android.view.View
|
||||||
|
import com.simplemobiletools.filepicker.R
|
||||||
|
import com.simplemobiletools.filepicker.adapters.ItemsAdapter
|
||||||
|
import com.simplemobiletools.filepicker.extensions.getFilenameFromPath
|
||||||
|
import com.simplemobiletools.filepicker.models.FileDirItem
|
||||||
|
import kotlinx.android.synthetic.main.directory_picker.view.*
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.comparisons.compareBy
|
||||||
|
|
||||||
|
class SelectFolderDialog : DialogFragment() {
|
||||||
|
val SELECT_FOLDER_REQUEST = 1
|
||||||
|
val SELECT_FOLDER_PATH = "path"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
lateinit var mPath: String
|
||||||
|
var mFirstUpdate: Boolean = true
|
||||||
|
|
||||||
|
fun newInstance(path: String): SelectFolderDialog {
|
||||||
|
mPath = path
|
||||||
|
mFirstUpdate = true
|
||||||
|
return SelectFolderDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var dialog: View
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
dialog = activity.layoutInflater.inflate(R.layout.directory_picker, null)
|
||||||
|
|
||||||
|
updateItems()
|
||||||
|
setupBreadcrumbs()
|
||||||
|
|
||||||
|
return AlertDialog.Builder(activity)
|
||||||
|
.setTitle(resources.getString(R.string.select_destination))
|
||||||
|
.setView(dialog)
|
||||||
|
.setPositiveButton(R.string.ok) { dialog, which -> sendResult() }
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateItems() {
|
||||||
|
var items = getItems(mPath)
|
||||||
|
if (!containsDirectory(items) && !mFirstUpdate) {
|
||||||
|
sendResult()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
items = items.sortedWith(compareBy({ !it.isDirectory }, { it.name }))
|
||||||
|
|
||||||
|
val adapter = ItemsAdapter(context, items)
|
||||||
|
dialog.directory_picker_list.adapter = adapter
|
||||||
|
//dialog.directory_picker_breadcrumbs.setInitialBreadcrumb(mPath)
|
||||||
|
dialog.directory_picker_list.setOnItemClickListener { adapterView, view, position, id ->
|
||||||
|
val item = items[position]
|
||||||
|
if (item.isDirectory) {
|
||||||
|
mPath = item.path
|
||||||
|
updateItems()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mFirstUpdate = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendResult() {
|
||||||
|
val intent = Intent()
|
||||||
|
intent.putExtra(SELECT_FOLDER_PATH, mPath)
|
||||||
|
targetFragment.onActivityResult(SELECT_FOLDER_REQUEST, Activity.RESULT_OK, intent)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupBreadcrumbs() {
|
||||||
|
/*dialog.directory_picker_breadcrumbs.setListener { id ->
|
||||||
|
val item = dialog.directory_picker_breadcrumbs.getChildAt(id).tag as FileDirItem
|
||||||
|
mPath = item.path
|
||||||
|
updateItems()
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getItems(path: String): List<FileDirItem> {
|
||||||
|
//val showHidden = Config.newInstance(context).showHidden
|
||||||
|
val items = ArrayList<FileDirItem>()
|
||||||
|
val base = File(path)
|
||||||
|
val files = base.listFiles()
|
||||||
|
if (files != null) {
|
||||||
|
for (file in files) {
|
||||||
|
if (!file.isDirectory)
|
||||||
|
continue
|
||||||
|
|
||||||
|
/* if (!showHidden && file.isHidden)
|
||||||
|
continue*/
|
||||||
|
|
||||||
|
val curPath = file.absolutePath
|
||||||
|
val curName = curPath.getFilenameFromPath()
|
||||||
|
val size = file.length()
|
||||||
|
|
||||||
|
items.add(FileDirItem(curPath, curName, file.isDirectory, getChildren(file), size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getChildren(file: File): Int {
|
||||||
|
if (file.listFiles() == null || !file.isDirectory)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return file.listFiles().size
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun containsDirectory(items: List<FileDirItem>): Boolean {
|
||||||
|
for (item in items) {
|
||||||
|
if (item.isDirectory) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.simplemobiletools.filepicker.extensions
|
||||||
|
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
fun Long.formatSize(): String {
|
||||||
|
if (this <= 0)
|
||||||
|
return "0 B"
|
||||||
|
|
||||||
|
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
||||||
|
val digitGroups = (Math.log10(toDouble()) / Math.log10(1024.0)).toInt()
|
||||||
|
return DecimalFormat("#,##0.#").format(this / Math.pow(1024.0, digitGroups.toDouble())) + " " + units[digitGroups]
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.simplemobiletools.filepicker.extensions
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.graphics.*
|
||||||
|
|
||||||
|
fun Resources.getColoredIcon(colorId: Int, resId: Int): Bitmap {
|
||||||
|
val options = BitmapFactory.Options()
|
||||||
|
options.inMutable = true
|
||||||
|
val bitmap = BitmapFactory.decodeResource(this, resId, options)
|
||||||
|
val paint = Paint()
|
||||||
|
val filter = PorterDuffColorFilter(getColor(colorId), PorterDuff.Mode.SRC_IN)
|
||||||
|
paint.colorFilter = filter
|
||||||
|
val canvas = Canvas(bitmap)
|
||||||
|
canvas.drawBitmap(bitmap, 0f, 0f, paint)
|
||||||
|
return bitmap
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.simplemobiletools.filepicker.extensions
|
||||||
|
|
||||||
|
fun String.getFilenameFromPath(): String {
|
||||||
|
return substring(lastIndexOf("/") + 1)
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.simplemobiletools.filepicker.models
|
||||||
|
|
||||||
|
class FileDirItem(val path: String, val name: String, val isDirectory: Boolean, val children: Int, val size: Long) :
|
||||||
|
Comparable<FileDirItem> {
|
||||||
|
|
||||||
|
override fun compareTo(other: FileDirItem): Int {
|
||||||
|
if (isDirectory && !other.isDirectory) {
|
||||||
|
return -1
|
||||||
|
} else if (!isDirectory && other.isDirectory) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return name.toLowerCase().compareTo(other.name.toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "FileDirItem{name=$name, isDirectory=$isDirectory, path=$path, children=$children, size=$size}"
|
||||||
|
}
|
||||||
|
}
|
17
simplefilepicker/src/main/res/drawable-v21/selector.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<selector>
|
||||||
|
<item
|
||||||
|
android:drawable="@color/activated_item_foreground"
|
||||||
|
android:state_activated="true"/>
|
||||||
|
</selector>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<ripple android:color="@color/pressed_item_foreground">
|
||||||
|
<item android:id="@android:id/mask">
|
||||||
|
<color android:color="@android:color/white"/>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
5
simplefilepicker/src/main/res/drawable/selector.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@color/pressed_item_foreground" android:state_pressed="true"/>
|
||||||
|
<item android:drawable="@color/activated_item_foreground" android:state_activated="true"/>
|
||||||
|
</selector>
|
21
simplefilepicker/src/main/res/layout/directory_picker.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/directory_picker_holder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.simplemobiletools.filemanager.Breadcrumbs
|
||||||
|
android:id="@+id/directory_picker_breadcrumbs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="@dimen/activity_margin"/>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/directory_picker_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
45
simplefilepicker/src/main/res/layout/list_item.xml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:foreground="@drawable/selector">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/item_holder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingRight="@dimen/activity_margin">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/item_icon"
|
||||||
|
android:layout_width="@dimen/icon_size"
|
||||||
|
android:layout_height="@dimen/icon_size"
|
||||||
|
android:paddingBottom="@dimen/medium_margin"
|
||||||
|
android:paddingTop="@dimen/medium_margin"
|
||||||
|
android:src="@mipmap/directory"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/item_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@+id/item_icon"
|
||||||
|
android:layout_toRightOf="@+id/item_icon"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:paddingLeft="@dimen/small_margin"
|
||||||
|
android:paddingTop="@dimen/small_margin"
|
||||||
|
android:text="Directory"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/item_details"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/item_name"
|
||||||
|
android:layout_toRightOf="@+id/item_icon"
|
||||||
|
android:paddingLeft="@dimen/small_margin"
|
||||||
|
android:text="1 KB"
|
||||||
|
android:textSize="@dimen/details_text_size"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</FrameLayout>
|
BIN
simplefilepicker/src/main/res/mipmap-hdpi/directory.png
Normal file
After Width: | Height: | Size: 135 B |
BIN
simplefilepicker/src/main/res/mipmap-hdpi/file.png
Normal file
After Width: | Height: | Size: 153 B |
BIN
simplefilepicker/src/main/res/mipmap-mdpi/directory.png
Normal file
After Width: | Height: | Size: 122 B |
BIN
simplefilepicker/src/main/res/mipmap-mdpi/file.png
Normal file
After Width: | Height: | Size: 133 B |
BIN
simplefilepicker/src/main/res/mipmap-xhdpi/directory.png
Normal file
After Width: | Height: | Size: 181 B |
BIN
simplefilepicker/src/main/res/mipmap-xhdpi/file.png
Normal file
After Width: | Height: | Size: 206 B |
BIN
simplefilepicker/src/main/res/mipmap-xxhdpi/directory.png
Normal file
After Width: | Height: | Size: 245 B |
BIN
simplefilepicker/src/main/res/mipmap-xxhdpi/file.png
Normal file
After Width: | Height: | Size: 283 B |
BIN
simplefilepicker/src/main/res/mipmap-xxxhdpi/directory.png
Normal file
After Width: | Height: | Size: 325 B |
BIN
simplefilepicker/src/main/res/mipmap-xxxhdpi/file.png
Normal file
After Width: | Height: | Size: 372 B |
11
simplefilepicker/src/main/res/values-de/strings.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Simple File Picker</string>
|
||||||
|
<string name="select_destination">Ziel auswählen</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Abbrechen</string>
|
||||||
|
|
||||||
|
<plurals name="items">
|
||||||
|
<item quantity="one">1 Datei/Ordner</item>
|
||||||
|
<item quantity="other">%1$d Dateien/Ordner</item>
|
||||||
|
</plurals>
|
||||||
|
</resources>
|
11
simplefilepicker/src/main/res/values-it/strings.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Simple File Picker</string>
|
||||||
|
<string name="select_destination">Seleziona destinazione</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Annulla</string>
|
||||||
|
|
||||||
|
<plurals name="items">
|
||||||
|
<item quantity="one">1 elemento</item>
|
||||||
|
<item quantity="other">%1$d elementi</item>
|
||||||
|
</plurals>
|
||||||
|
</resources>
|
11
simplefilepicker/src/main/res/values-ja/strings.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Simple File Picker</string>
|
||||||
|
<string name="select_destination">宛先を選択</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
|
||||||
|
<plurals name="items">
|
||||||
|
<item quantity="one">1 アイテム</item>
|
||||||
|
<item quantity="other">%1$d アイテム</item>
|
||||||
|
</plurals>
|
||||||
|
</resources>
|
11
simplefilepicker/src/main/res/values-pt-rPT/strings.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Simple File Picker</string>
|
||||||
|
<string name="select_destination">Selecionar destino</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Cancelar</string>
|
||||||
|
|
||||||
|
<plurals name="items">
|
||||||
|
<item quantity="one">1 item</item>
|
||||||
|
<item quantity="other">%1$d itens</item>
|
||||||
|
</plurals>
|
||||||
|
</resources>
|
11
simplefilepicker/src/main/res/values-sv/strings.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Simple File Picker</string>
|
||||||
|
<string name="select_destination">Välj mål</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
|
||||||
|
<plurals name="items">
|
||||||
|
<item quantity="one">1 objekt</item>
|
||||||
|
<item quantity="other">%1$d objekt</item>
|
||||||
|
</plurals>
|
||||||
|
</resources>
|
6
simplefilepicker/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="thumbnail_grey">#33000000</color>
|
||||||
|
<color name="pressed_item_foreground">#08000000</color>
|
||||||
|
<color name="activated_item_foreground">#44888888</color>
|
||||||
|
</resources>
|
9
simplefilepicker/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<resources>
|
||||||
|
<dimen name="activity_margin">16dp</dimen>
|
||||||
|
<dimen name="small_margin">6dp</dimen>
|
||||||
|
<dimen name="medium_margin">10dp</dimen>
|
||||||
|
<dimen name="icon_size">48dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="details_text_size">12sp</dimen>
|
||||||
|
<dimen name="normal_text_size">14sp</dimen>
|
||||||
|
</resources>
|
11
simplefilepicker/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Simple File Picker</string>
|
||||||
|
<string name="select_destination">Select destination</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
|
||||||
|
<plurals name="items">
|
||||||
|
<item quantity="one">1 item</item>
|
||||||
|
<item quantity="other">%1$d items</item>
|
||||||
|
</plurals>
|
||||||
|
</resources>
|