2012-07-27 47 views
0

我正在尝试使用Mono for Android将代码从this tutorial移植到C#。这里是我的代码:Mono for Android:显示文件选择器?

FileLayout.axml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" 
    android:layout_width="fill_parent"> 
    <TextView 
     android:text="@+id/TextView01" 
     android:id="@+id/TextView01" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:singleLine="true" 
     android:textStyle="bold" 
     android:layout_marginTop="5dip" 
     android:layout_marginLeft="5dip" /> 
    <TextView 
     android:text="@+id/TextView02" 
     android:id="@+id/TextView02" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="10dip" /> 
</LinearLayout> 

FileArrayAdapter.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using Android.App; 
using Android.Content; 
using Android.OS; 
using Android.Runtime; 
using Android.Views; 
using Android.Widget; 

namespace FileChooser 
{ 
    public class FileArrayAdapter : ArrayAdapter<Option> 
    { 

     private Context c; 
     private int id; 
     private List<Option> items; 

     public FileArrayAdapter(Context context, int textViewResourceId, 
       List<Option> objects) 
      : base(context, textViewResourceId, objects) 
     { 

      c = context; 
      id = textViewResourceId; 
      items = objects; 
     } 

     public Option getItem(int i) 
     { 
      return items[i]; 
     } 
     public View getView(int position, View convertView, ViewGroup parent) 
     { 
      View v = convertView; 
      if (v == null) 
      { 
       LayoutInflater vi = (LayoutInflater)c.GetSystemService(Context.LayoutInflaterService); 
       v = vi.Inflate(id, null); 
      } 
      Option o = items[position]; 
      if (o != null) 
      { 
       TextView t1 = (TextView)v.FindViewById(Resource.Id.TextView01); 
       TextView t2 = (TextView)v.FindViewById(Resource.Id.TextView02); 

       if (t1 != null) 
        t1.Text = o.getName().ToString(); 
       if (t2 != null) 
        t2.Text = o.getData().ToString(); 

      } 
      return v; 
     } 


    } 

} 

Activity1.cs:

using System; 
using System.Collections; 
using System.Collections.Generic; 
using Android.App; 
using Android.Content; 
using Android.Runtime; 
using Android.Util; 
using Android.Views; 
using Android.Widget; 
using Android.OS; 
using Java.IO; 
using Environment = Android.OS.Environment; 


namespace FileChooser 
{ 
    [Activity(Label = "FileChooser", MainLauncher = true, Icon = "@drawable/icon")] 
    public class Activity1 : ListActivity 
    { 
     private File currentDir; 
     private FileArrayAdapter adapter; 

     protected override void OnCreate(Bundle bundle) 
     { 
      base.OnCreate(bundle); 

      currentDir = new File(Environment.RootDirectory.AbsolutePath); 
      fill(currentDir); 

     } 

     private void fill(File f) 
     { 
      File[] dirs = f.ListFiles(); 

      Title = ("Current Dir: " + f.Name); 
      List<Option> dir = new List<Option>(); 
      List<Option> fls = new List<Option>(); 

      try 
      { 
       foreach (var ff in dirs) 
        if (ff.IsDirectory) 
         dir.Add(new Option(ff.Name, "Folder", ff.AbsolutePath)); 
        else 
         fls.Add(new Option(ff.Name, "File Size: " + ff.Length(), ff.AbsolutePath)); 


       dir.AddRange(fls); 

       if (!String.Equals(f.Name, "sdcard", comparisonType: StringComparison.InvariantCultureIgnoreCase)) 
        dir.Insert(0, new Option("..", "Parent Directory", f.Parent)); 

       adapter = new FileArrayAdapter(this, Resource.Layout.FileLayout, dir); 
       this.ListAdapter = adapter; 

      } 
      catch (Exception e) 
      { 
       System.Diagnostics.Debug.WriteLine("Error: ", e.Message); 

      } 


     } 



    } 
} 

我得到以下错误:

The program 'Mono' has exited with code 255 (0xff). 

我在最后一条语句后放置了一个断点。这里是我的局部变量的sceenshot:enter image description here

回答

0

我通过对FileArrayAdapter.cs进行更改而得到了工作。我没有实现ArrayAdapter,而是实现了BaseAdapter类。 。切换到适当的基类也让我意识到,实施方法中的大写字母是错误的。

它的一个棘手的部分是在GetItem()方法中将List<Option> item转换为JavaObject

下面是修改后的代码:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using Android.App; 
using Android.Content; 
using Android.OS; 
using Android.Runtime; 
using Android.Views; 
using Android.Widget; 
using Android.Runtime; 

namespace FileChooser 
{ 
    public class FileArrayAdapter : BaseAdapter<Option> 
    { 

     private Context c; 
     private int id; 
     private List<Option> items; 

     public FileArrayAdapter(Context context, int textViewResourceId, 
       List<Option> objects) 

     { 

      c = context; 
      id = textViewResourceId; 
      items = objects; 
     } 

     public override View GetView(int position, View convertView, ViewGroup parent) 
     { 
      View v = convertView; 
      if (v == null) 
      { 
       LayoutInflater vi = (LayoutInflater)c.GetSystemService(Context.LayoutInflaterService); 
       v = vi.Inflate(id, null); 
      } 
      Option o = items[position]; 
      if (o != null) 
      { 
       TextView t1 = (TextView)v.FindViewById(Resource.Id.TextView01); 
       TextView t2 = (TextView)v.FindViewById(Resource.Id.TextView02); 

       if (t1 != null) 
        t1.Text = o.getName().ToString(); 
       if (t2 != null) 
        t2.Text = o.getData().ToString(); 

      } 
      return v; 
     } 



     public override Option this[int position] 
     { 
      get { return items[position]; } 
     } 

     public override int Count 
     { 
      get { return items.Count; } 
     } 

     public override long GetItemId(int position) 
     { 
      return position; 
     } 

    } 

} 
2

我可能在这里脱颖而出,但我前段时间写了一个简单的轻量级文件拣选小部件。

package com.skype.widget; 
import java.io.File; 
import java.util.ArrayList; 

import android.content.Context; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 

/** 
* General purpose, light-weight file explorer widget.<br> 
* Upon initialization, it will point at the root of the filesystem, at which 
* point you can manipulate it with {@link #browseToLocation(String)} 
* 
* @author Aleksandar Milenkovic 
*/ 

public class FileBrowser extends ListView implements AdapterView.OnItemClickListener 
{ 
/** 
* Use display mode to toggle between absolute and relative display modes. 
*/ 
public enum DISPLAYMODE 
{ 
    ABSOLUTE, RELATIVE; 
} 

/** 
* Use work mode to toggle between folder-only and files-and-folders mode. 
*/ 
public enum WORKMODE 
{ 
    FOLDER_ONLY, FILE_AND_FOLDER; 
} 

public static final String  ROOT  = "/"; 
public static final String  LOGTAG  = "FileBrowser"; 

@SuppressWarnings("unused") 
private Context     context; 

private final DISPLAYMODE  displayMode = DISPLAYMODE.RELATIVE; 
private WORKMODE    workMode = WORKMODE.FILE_AND_FOLDER; 
private ArrayList<String>  directoryEntries; 
private File     currentDirectory; 
private ArrayAdapter<String> mAdapter; 


public FileBrowser(Context context) 
{ 
    this(context, null, 0); 
} 

public FileBrowser(Context context, AttributeSet attrs, int defStyle) 
{ 
    super(context, attrs, defStyle); 
    this.context = context; 
    //init members 
    directoryEntries = new ArrayList<String>(); 
    mAdapter = new ArrayAdapter<String>(context, R.layout.file_browser_entry, this.directoryEntries); 
    this.setAdapter(mAdapter); 

    //browse to root 
    browseToLocation(ROOT); 

    //refresh UI elements 
    mAdapter.notifyDataSetChanged(); 
    setOnItemClickListener(this); 
} 

public FileBrowser(Context context, AttributeSet attrs) 
{ 
    this(context, attrs, 0); 
} 


/** 
* This function browses to the root-directory of the file-system. 
* 
* @param location 
*   the absolute path you want to browse to. 
*/ 
public void browseToLocation(String location) 
{ 
    browseTo(new File(location)); 
} 

/** 
* This function browses up one level according to the field: 
* currentDirectory 
*/ 
private void upOneLevel() 
{ 
    Log.d(LOGTAG, "upOneLevel()"); 
    if (currentDirectory.getAbsolutePath() == ROOT) return; 
    if (this.currentDirectory.getParent() != null) this.browseTo(this.currentDirectory.getParentFile()); 
} 

private void browseTo(final File aDirectory) 
{ 
    Log.d(LOGTAG, "browseTo()"); 
    if (aDirectory.isDirectory()) 
    { 
     this.currentDirectory = aDirectory; 
     fill(aDirectory.listFiles()); 
    } else 
    { 
     Log.d(LOGTAG, aDirectory.getAbsolutePath()); 
    } 
} 

private void fill(File[] files) 
{ 
    Log.d(LOGTAG, "fill()"); 
    this.directoryEntries.clear(); 

    // Add the "." and the ".." == 'Up one level' 
    this.directoryEntries.add("."); 
    if (this.currentDirectory.getParent() != null) this.directoryEntries.add(".."); 

    switch (this.workMode) 
    { 
     case FOLDER_ONLY: 
      switch (this.displayMode) 
      { 
       case ABSOLUTE: 
        for (File file : files) 
        { 
         if (file.isDirectory()) this.directoryEntries.add(file.getPath() + "/"); 
        } 
        break; 
       case RELATIVE: // On relative Mode, we have to add the current-path to the beginning 
        int currentPathStringLenght = this.currentDirectory.getAbsolutePath().length(); 
        for (File file : files) 
        { 
         if (file.isDirectory()) 
          this.directoryEntries.add(file.getAbsolutePath().substring(currentPathStringLenght) + "/"); 
        } 
        break; 
      } 
      break; 

     case FILE_AND_FOLDER: 
      switch (this.displayMode) 
      { 
       case ABSOLUTE: 
        for (File file : files) 
        { 
         if (file.isDirectory()) 
          this.directoryEntries.add(file.getPath() + "/"); 
         else 
          this.directoryEntries.add(file.getPath()); 
        } 
        break; 
       case RELATIVE: // On relative Mode, we have to add the current-path to the beginning 
        int currentPathStringLenght = this.currentDirectory.getAbsolutePath().length(); 
        for (File file : files) 
        { 
         if (file.isDirectory()) 
          this.directoryEntries.add(file.getAbsolutePath().substring(currentPathStringLenght) + "/"); 
         else 
          this.directoryEntries.add(file.getAbsolutePath().substring(currentPathStringLenght)); 
        } 
        break; 
      } 
    } 

} 

/** 
* Internal onItemClick method that handles browsing and displaying.<br> 
* <b>Make sure to call this at the start of the outer onItemClick.</b> 
*/ 
@Override 
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) 
{ 
    String selectedFileString = directoryEntries.get(arg2); 
    Log.d(LOGTAG, "onItemClick() fired!"); 
    if (selectedFileString.equals(".")) 
    { 
     // Refresh 
     browseTo(currentDirectory); 
    } else if (selectedFileString.equals("..")) 
    { 
     upOneLevel(); 
    } else 
    { 
     File clickedFile = null; 
     switch (displayMode) 
     { 
      case RELATIVE: 
       clickedFile = new File(currentDirectory.getAbsolutePath() + directoryEntries.get(arg2)); 
       break; 
      case ABSOLUTE: 
       clickedFile = new File(directoryEntries.get(arg2)); 
       break; 
     } 
     if (clickedFile != null) browseTo(clickedFile); 
    } 
    mAdapter.notifyDataSetChanged(); 
    this.postInvalidate(); 
} 

/** 
* Gets the current path in absolute form. 
* 
* @return the absolute path pointing to the current directory. 
*/ 
public String getCurrentPath() 
{ 
    return currentDirectory.getAbsolutePath(); 
} 

/** 
* Method used for setting the work mode of this widget. <br> 
* It can be either {@link WORKMODE#FILE_AND_FOLDER} or {@link WORKMODE#FOLDER_ONLY} 
* @param wm 
* the workmode to use. 
*/ 
public void setWorkMode(WORKMODE wm) 
{ 
    this.workMode = wm; 
} 

/** 
* Returns the current workmode of this widget. 
* @return 
* {@link #workMode} as {@link WORKMODE} enum 
*/ 
public WORKMODE getWorkMode() 
{ 
    return workMode; 
} 

}

用法:

final FileBrowser fb = (FileBrowser) dialog.findViewById(R.id.folder_list); 
    fb.setWorkMode(FileBrowser.WORKMODE.FOLDER_ONLY); 
    fb.setOnItemClickListener(new AdapterView.OnItemClickListener() 
    { 
     @Override 
     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) 
     { 
      fb.onItemClick(arg0, arg1, arg2, arg3); 

      txt.setText(fb.getCurrentPath()); 
      savingPath = fb.getCurrentPath() + "/"; 
     } 
    }); 

抱歉,如果这不是你想要的。

+0

这看起来优秀..我不知道如何使用它在C#中,虽然 – 2012-07-27 16:26:14

+0

哦扣,这是Java,我还以为你移植的C#代码到Java 。我的坏...仍然,这一个可能比教程更好的作品(如果不是相似的,我鞭打了一个轻的filepicker小部件的例子,并完全失败),所以你可能能够将它移植到C#。 – Shark 2012-07-27 16:27:17