我正在尝试使用this tutorial将代码从Mono for Android移植到C#。这是我的代码:
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).
我在最后一个声明之后放了一个断点。这是我的局部变量的一个情景:
答案 0 :(得分: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() + "/";
}
});
抱歉,如果那不是您想要的。
答案 1 :(得分:0)
我通过对FileArrayAdapter.cs
进行更改来实现它。我没有实现ArrayAdapter,而是实现了BaseAdapter类。 。切换到正确的基类也让我意识到实现的方法中的大写是错误的。
其中一个棘手的部分是将List<Option> item
转换为GetItem()方法中的Java
Object
。
以下是修订后的代码:
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;
}
}
}