android中使用Dialog实现目录选择器

来源:互联网 发布:行知教育基地 编辑:程序博客网 时间:2024/06/06 05:40

在CSDN找了好几个目录选择器,都是用Dialog实现的。但都有一个巨大的问题,选择了半天,无法将选择的目录的String传回到调用者,因为没有太大意义。下面是我解决的历史思路。

1、用Activity实现,在调用Activity与被调用Activity之间传递参数,自然也可以传递选择的目录的String。这是可以实现的,也是我实现的第一个版本,比较简单(另文描述)。但还是不死心,就想通过Dialog来搞定。

2、通过StringBuffer等传递参数,不知为何失败,又因为不是OO的思路,失去兴趣。

3、通过AlertDialog的setPositiveButton来实现。但这个PositiveButton的处理代码只能在调用者的环境中,还是苦于无法传递回结果目录的字符串,又回到了问题本身。在这种情况下,反而不如Dialog更方便(因为在Dialog中可以任意添加Button,并处理Button的事件,而在AlertDialog,最好是顺着其设计目的来使用)。

4、将Dialog或AlertDialog的继承(或作为自定义类的成员变量)作为调用者的内部类,因为这个内部类可以方便地访问外部类的成员和方法,估计可以肯快就实现,但由于严重违反MVC编程风格,放弃。

5、通过向File、ContentProvider、SharedPreference一定也能实现(虽然有些同步呀、触发啦需要处理一下),不想这样做,放弃。

6、忽然有一天,发现Android3.0以上都不能直接访问HttpURLConnection,必须另起一个线程实现。受到启发,也另起一个线程,在这个线程中等待用户按下Button,修改mBtnOkIsPressed属性为true。一旦等到这个事件,获得选择的目录的String,再在Handler中主动关闭这个Dialog。比较复合OO思想,遂实现。


代码如下:

代码1:dialog_choose_dir.xml  --  这部分与网上其他博文里几乎一模一样。

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:orientation="vertical" >


    <LinearLayout

        android:layout_width="fill_parent"

        android:layout_height="40dip"

        android:orientation="horizontal" >


        <Button

            android:id="@+id/btn_home"

            android:layout_width="40dip"

            android:layout_height="40dip"

            android:layout_gravity="left"

            android:layout_weight="1"

            android:text="@string/button_home" />


        <LinearLayout

            android:id="@+id/dir_layout"

            android:layout_width="140dip"

            android:layout_height="35dip"

            android:layout_weight="1"

            android:gravity="center"

            android:orientation="horizontal" >

        </LinearLayout>


        <Button

            android:id="@+id/btn_back"

            android:layout_width="40dip"

            android:layout_height="40dip"

            android:layout_gravity="right"

            android:layout_weight="1"

            android:text="@string/button_back" />

    </LinearLayout>


   <RelativeLayout

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:orientation="vertical" >


        <!-- 注意虽然这个Button在前面描述,但其位置却是在底部 -->


        <Button

            android:id="@+id/btn_ok"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:layout_alignParentBottom="true"

            android:text="@string/button_ok" />


        <ListView

            android:id="@+id/list_dir"

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"

            android:layout_above="@id/btn_ok" />

    </RelativeLayout>


</LinearLayout>


代码2:ChooseDirDialog.java

package com.acesage.android4try;


import java.io.File;

import java.util.ArrayList;

import java.util.List;


import android.app.Dialog;

import android.content.Context;

import android.os.Environment;

import android.os.Handler;

import android.view.Gravity;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.Button;

import android.widget.EditText;

import android.widget.LinearLayout;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.AdapterView.OnItemClickListener;


//public class ChooseDirDialog extends Dialog {//注意,继承方式会发生栈溢出错误!

public class ChooseDirDialog {

private Dialog mDialog// 应采用成员变量形式

private Context mContext;


private ListView mListView;

ArrayAdapter<String> mAdapter;

ArrayList<String> mArrayList = new ArrayList<String>(); //不要用ArrayList,而用ArrayList<T>更安全


private String mPath;  //选择的目录

private boolean btnOkIsPressed=false;  //初始化时,btnOk没有按下,所以为false

public boolean getBtnOkIsPressed(){

return btnOkIsPressed;

}


private TextView titleTextView;

private EditText titleEditText;

private Button btnHomebtnBackbtnOk;

private LinearLayout titleLinearLayout;


private int mType = 1;

private String[] mFileType = null;


public final static int TypeOpen = 1;

public final static int TypeSave = 2;


public ChooseDirDialog(Context context, int type, String[] fileType) {

this.mContext = context;

this.mType = type;

this.mFileType = fileType;


mDialog = new Dialog(mContext);  //在这里new并获得Dialog的实例


//填充界面并初始化各种控件

View view = LayoutInflater.from(mContext).inflate( 

R.layout.dialog_choose_dirnull);

mDialog.setContentView(view);

mDialog.setTitle(R.string.title_choose_dir);


mPath = getRootDir();

mArrayList = (ArrayList<String>) getDirs(mPath);

mAdapter = new ArrayAdapter<String>(mContext,

android.R.layout.simple_list_item_1mArrayList);


mListView = (ListView) view.findViewById(R.id.list_dir);

mListView.setAdapter(mAdapter);


mListView.setOnItemClickListener(lvLis);


btnHome = (Button) view.findViewById(R.id.btn_home);// Java多级目录的生成

btnHome.setOnClickListener(new HomeClickListener());


btnBack = (Button) view.findViewById(R.id.btn_back);

btnBack.setOnClickListener(new BackClickListener());


btnOk = (Button) view.findViewById(R.id.btn_ok);

btnOk.setOnClickListener(new OkClickListener());


titleLinearLayout = (LinearLayout) view.findViewById(R.id.dir_layout);


if (mType == TypeOpen) {

titleTextView = new TextView(mContext);

titleLinearLayout.addView(titleTextView);

titleTextView.setText(mPath);

else if (mType == TypeSave) {

titleEditText = new EditText(mContext);

titleEditText.setWidth(240);

titleEditText.setHeight(70);

titleEditText.setGravity(Gravity.CENTER);

titleEditText.setPadding(0, 2, 0, 0);

titleLinearLayout.addView(titleEditText);

titleEditText.setText("FileName");

}


}


// 动态更新ListView

Runnable AddThread = new Runnable() {


@Override

public void run() {

// TODO Auto-generated method stub

mArrayList.clear();

// System.out.println("Runnable mPath:"+mPath);


// 必须得用这种方法为arr赋值才能更新

List<String> temp = getDirs(mPath);

for (int i = 0; i < temp.size(); i++)

mArrayList.add(temp.get(i));

mAdapter.notifyDataSetChanged();

}

};


private OnItemClickListener lvLis = new OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,

long arg3) {

String temp = (String) arg0.getItemAtPosition(arg2);

// System.out.println("OnItemClick path1:"+mPath);

if (temp.equals(".."))

mPath = getFatherDir(mPath);

else if (mPath.equals("/"))

mPath = mPath + temp;

else

mPath = mPath + "/" + temp;


// System.out.println("OnItemClick path2"+mPath);

if (mType == TypeOpen// 还应解决,如选择为文件,而非目录的情况:不应该做任何动作

titleTextView.setText(mPath);

// 还应解决,如为TypeSave,选择文件情况:应更新文件名


Handler handler = new Handler();

handler.post(AddThread);

}

};


private List<String> getDirs(String ipath) {

List<String> file = new ArrayList<String>();

File[] myFile = new File(ipath).listFiles();

if (myFile == null) {

file.add("..");


else

for (File f : myFile) {

// 过滤目录

if (f.isDirectory()) {

String tempf = f.toString();

int pos = tempf.lastIndexOf("/");

String subTemp = tempf.substring(pos + 1, tempf.length());

// String subTemp =

// tempf.substring(mPath.length(),tempf.length());

file.add(subTemp);

// System.out.println("files in dir:"+subTemp);

}

// 过滤知道类型的文件

if (f.isFile() && mFileType != null) {

for (int i = 0; i < mFileType.length; i++) {

int typeStrLen = mFileType[i].length();


String fileName = f.getPath().substring(

f.getPath().length() - typeStrLen);

if (fileName.toLowerCase().equals(mFileType[i])) {

file.add(f.toString().substring(mPath.length() + 1,

f.toString().length()));

}

}

}

}


if (file.size() == 0)

file.add("..");


// System.out.println("file[0]:"+file.get(0)+" File size:"+file.size());

return file;

}


private String getSDPath() {

File sdDir = null;

boolean sdCardExist = Environment.getExternalStorageState().equals(

android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在

if (sdCardExist) {

sdDir = Environment.getExternalStorageDirectory();// 获取根目录

}

if (sdDir == null) {

return null;

}

return sdDir.toString();


}


private String getRootDir() {

String root = "/";


mPath = getSDPath();

if (mPath == null)

mPath = "/";


return root;

}


private String getFatherDir(String path) {

String subpath = null;


int pos = path.lastIndexOf("/");


if (pos == path.length()) {

path = path.substring(0, path.length() - 1);

pos = path.lastIndexOf("/");

}


subpath = path.substring(0, pos);


if (pos == 0)

subpath = path;


return subpath;

}


private final class HomeClickListener implements View.OnClickListener {


@Override

public void onClick(View v) {

mPath = getRootDir();

if (mType == TypeOpen)

titleTextView.setText(mPath);

Handler handler = new Handler();

handler.post(AddThread);

}


}


private final class BackClickListener implements View.OnClickListener {


@Override

public void onClick(View v) {

mPath = getFatherDir(mPath);

if (mType == TypeOpen)

titleTextView.setText(mPath);

Handler handler = new Handler();

handler.post(AddThread);

}


}


private final class OkClickListener implements View.OnClickListener {


@Override

public void onClick(View v) {

//仅仅修改btnOkIsPressed的状态,不尝试从这里传递任何参数给调用者,那是绝对不可能的(因为调用者对这个对象来讲,是不可见的)。

btnOkIsPressed=true;  

}


}


public String getResultPath() {

String resultPath;

if (mType == TypeSave) {

resultPath = mPath + "/"

titleEditText.getEditableText().toString();

else {

resultPath = mPath;

}

return resultPath;

}

public void show(){

mDialog.show();

}

public void dismiss(){

mDialog.dismiss();

}


}


代码片段3:(可以被放在某个Activity,也可以放在某个Fragment。这个案例是在一个Fragment,如要放在Activity中,要修改其中获得context的代码)(这个Fragment的布局及其简单,就不列出其xml文档了,至于02、04一类的编号,没有任何意义。那时因为当时做了好多调试,这里只摘出与本文有关的部分)


public class Fragment02 extends Fragment {
private EditText mMessage02;
private Button mButtonChoose04; 


ChooseDirDialog mChooseDirDialog = null;
public final int MESSAGE_RESULT_PATH_IS_OK = 1;
private Handler mHandler = new Handler() {  //处理由另起的线程返回的消息
@Override
public void handleMessage(Message msg) {
if (MESSAGE_RESULT_PATH_IS_OK == msg.what) {
String data = (String) msg.obj;
mMessage02.setText(data);
mChooseDirDialog.dismiss();
}
super.handleMessage(msg);
}


};


public Fragment02() {
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater
.inflate(R.layout.fragment_02, container, false);


return rootView;
}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);


mMessage02 = (EditText) this.getActivity().findViewById(
R.id.text_message_02);




mButtonChoose04 = (Button) this.getActivity().findViewById(
R.id.alert_choose_dir_04);
mButtonChoose04.setOnClickListener(new ButtonChoose04ClickListener());


}




private final class ButtonChoose04ClickListener implements
android.view.View.OnClickListener {


@Override
public void onClick(View v) {
mChooseDirDialog = new ChooseDirDialog(getActivity(),
ChooseDirDialog.TypeOpen, new String[] { "jpg" });
mChooseDirDialog.show();
new Thread(new TransferResultPathThread()).start();
}
}


public class TransferResultPathThread implements Runnable {


@Override
public void run() {
String resultStr = null;
try {
while (!mChooseDirDialog.getBtnOkIsPressed()) {
resultStr = mChooseDirDialog.getResultPath();
Thread.sleep(100);
}
Message message = Message.obtain(mHandler,
MESSAGE_RESULT_PATH_IS_OK, resultStr);
message.sendToTarget();


} catch (Exception e) {
e.printStackTrace();
}
}


}


}



最后吐槽一句:但如果Android直接提供像JFileChooser这样的对象多好。这是在一个看图软件的Java Application中的一段的代码:多简洁:)

JFileChooser fileChooser = new JFileChooser();

fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

int returnVal = fileChooser.showOpenDialog(this);

if (returnVal == JFileChooser.APPROVE_OPTION) {

// System.out.print(fileChooser.getSelectedFile().getAbsolutePath());

rif.setCurrentDirectoryAbsolutePath(fileChooser

.getSelectedFile().getAbsolutePath());

rif.openRecursiveImageFiles();

}


0 0
原创粉丝点击