Preference、設定画面で端末のディレクトリを指定するのに、EditTextPreference で入力させるのは、
ちょっとユーザにとっては辛い。
以下のようなダイアログで選択させたい。
DialogPreference で実現する。
package org.uran;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
import org.uran.R;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
/**
* DirectorySelectPreference
*/
public class DirectorySelectPreference extends DialogPreference{
static String mCurrentPath;
static TextView mPathText;
static ListView mListView;
static List<File> mFileList = new ArrayList<File>();
static String mRootPath;
final static FileFilter dirGetFilter = new FileFilter(){
@Override
public boolean accept(File file){
// 必要に応じてフィルタ条件を追加
return file.isDirectory();
}
};
final static Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
String path = msg.obj.toString();
removeMessages(0);
mCurrentPath = path;
mPathText.setText(path);
mFileList.clear();
if (path.equals(mRootPath)==false) mFileList.add(new File(path+"/../"));
for(File file : new File(path).listFiles(dirGetFilter)){
mFileList.add(file);
}
*1.notifyDataSetChanged();
}
};
public DirectorySelectPreference(Context context,AttributeSet attrs){
super(context, attrs);
mRootPath = Environment.getExternalStorageDirectory().getAbsolutePath();
}
@Override
protected View onCreateDialogView(){
LinearLayout layout = new LinearLayout(getContext());
layout.setOrientation(LinearLayout.VERTICAL);
mPathText = new TextView(getContext(),null, android.R.attr.textAppearanceMedium);
// left, top, right, bottom
mPathText.setPadding(10, 6, 2, 6);
mPathText.setTextColor(0xff000000);
mPathText.setBackgroundColor(0xffffffff);
mPathText.setText(getPersistedString(mCurrentPath==null ? mRootPath : mCurrentPath));
layout.addView(mPathText);
mListView = new ListView(getContext());
mListView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
mListView.setAdapter(new ArrayAdapter<File>(getContext(), 0, mFileList){
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@Override
public View getView(int position,View convertView,ViewGroup parent){
View view = convertView==null ? inflater.inflate(R.layout.directory_row, null) : convertView;
TextView tv = (TextView)view.findViewById(R.id.fileTextView);
File file = mFileList.get(position);
tv.setText(file.getName());
return view;
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
// 選択後の処理
BaseAdapter adapter = (BaseAdapter)parent.getAdapter();
File file = (File)adapter.getItem(position);
if (file.isDirectory()){
if (file.canRead() && file.canWrite()){
String path = file.getAbsolutePath();
if (path.endsWith("/..")){
path = file.getParentFile().getParent();
}
Message message = Message.obtain();
message.obj = path;
message.arg1 = position;
mHandler.sendMessage(message);
}else{
Toast.makeText(getContext(), "権限がありません", Toast.LENGTH_SHORT).show();
mListView.setItemChecked(position, false);
}
}
}
});
layout.addView(mListView);
mFileList.clear();
String path = mCurrentPath==null ? getPersistedString(mRootPath) : mCurrentPath;
if (path.equals(mRootPath)==false) mFileList.add(new File(path+"/../"));
for(File f : new File(path).listFiles(dirGetFilter)){
mFileList.add(f);
}
return layout;
}
@Override
protected void onAttachedToActivity(){
super.onAttachedToActivity();
String path = getPersistedString(mRootPath);
setSummary(path);
}
@Override
protected void onDialogClosed(boolean positiveResult){
if (positiveResult){
persistString(mPathText.getText().toString());
setSummary(mPathText.getText().toString());
}
}
}
これと、フォルダ、ファイルの画像と、以下、file_row.xml を用意する
<?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:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_menu_folder" />
<TextView
android:id="@+id/fileTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#ffffff" />
</LinearLayout>
Preference の XMLは、以下のように書けばよい。
<org.uran.DirectorySelectPreference
android:key="outdirectory"
android:title="書込み先"
android:dialogTitle="書込み先指定" >
</org.uran.DirectorySelectPreference>
*1:BaseAdapter)mListView.getAdapter(