我正在尝试用导航抽屉实现一个简单的文件管理器。我正在使用自定义列表视图来显示 SDcard 的内容。这些是我的文件
activity_main_drawer.xml(主布局)
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- The main content view -->
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<!-- The navigation drawer -->
<ListView
android:id="@+id/drawer"
android:layout_width="320dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#F3F3F4"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
file_view.xml(用作自定义列表视图)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:orientation="vertical" android:layout_width="fill_parent">
<ImageView
android:id="@+id/fd_Icon1"
android:layout_width="50dip"
android:layout_height="50dip" >
</ImageView>
<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_toRightOf="@+id/fd_Icon1"
android:layout_marginTop="5dip"
android:layout_marginLeft="5dip">
</TextView>
<TextView android:text="@+id/TextView02"
android:id="@+id/TextView02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/fd_Icon1"
android:layout_below="@+id/TextView01"
android:layout_marginLeft="10dip">
</TextView>
<TextView android:text="@+id/TextViewDate"
android:id="@+id/TextViewDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/TextView01"
android:layout_alignParentRight="true"
android:layout_marginLeft="5dip">
</TextView>
</RelativeLayout>
MainActivity.java
public class MainActivity extends FragmentActivity {
private ListView mDrawerList;
private DrawerLayout mDrawer;
private CustomActionBarDrawerToggle mDrawerToggle;
private String[] menuItems;
private FileChooser filechooser;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_drawer);
//Gets the path of external storage
// enable ActionBar app icon to behave as action to toggle nav drawer
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
// set a custom shadow that overlays the main content when the drawer
// opens
mDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
_initMenu();
mDrawerToggle = new CustomActionBarDrawerToggle(this, mDrawer);
mDrawer.setDrawerListener(mDrawerToggle);
Fragment fragment = new FileChooser();
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, fragment).commit();
}
private void _initMenu() {
NsMenuAdapter mAdapter = new NsMenuAdapter(this);
// Add Header
mAdapter.addHeader(R.string.ns_menu_main_header);
// Add first block
menuItems = getResources().getStringArray(R.array.ns_menu_items);
String[] menuItemsIcon = getResources().getStringArray(
R.array.ns_menu_items_icon);
int res = 0;
for (String item : menuItems) {
int id_title = getResources().getIdentifier(item, "string",
this.getPackageName());
int id_icon = getResources().getIdentifier(menuItemsIcon[res],
"drawable", this.getPackageName());
NsMenuItemModel mItem = new NsMenuItemModel(id_title, id_icon);
if (res == 1)
mItem.counter = 12; // it is just an example...
if (res == 3)
mItem.counter = 3; // it is just an example...
mAdapter.addItem(mItem);
res++;
}
mAdapter.addHeader(R.string.ns_menu_main_header2);
//add second block
menuItems = getResources().getStringArray(R.array.ns_menu_items);
String[] menuItemsIcon1 = getResources().getStringArray(
R.array.ns_menu_items_icon);
int res1 = 0;
for (String item : menuItems) {
int id_title = getResources().getIdentifier(item, "string",
this.getPackageName());
int id_icon = getResources().getIdentifier(menuItemsIcon1[res1],
"drawable", this.getPackageName());
NsMenuItemModel mItem = new NsMenuItemModel(id_title, id_icon);
if (res1 == 1)
mItem.counter = 12; // it is just an example...
if (res1 == 3)
mItem.counter = 3; // it is just an example...
mAdapter.addItem(mItem);
res1++;
}
mDrawerList = (ListView) findViewById(R.id.drawer);
if (mDrawerList != null)
mDrawerList.setAdapter(mAdapter);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content
// view
boolean drawerOpen = mDrawer.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_save).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
/*
* The action bar home/up should open or close the drawer.
* ActionBarDrawerToggle will take care of this.
*/
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
/*
* This is used to toggle the title on the action bar
*/
private class CustomActionBarDrawerToggle extends ActionBarDrawerToggle {
public CustomActionBarDrawerToggle(Activity mActivity,
DrawerLayout mDrawerLayout) {
super(mActivity, mDrawerLayout, R.drawable.ic_drawer,
R.string.ns_menu_open, R.string.ns_menu_close);
}
@Override
public void onDrawerClosed(View view) {
getActionBar().setTitle(getString(R.string.ns_menu_close));
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
@Override
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(getString(R.string.ns_menu_open));
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
}
/*
* Action to be performed when clicking item on the drawer
*/
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Highlight the selected item, update the title, and close the
// drawer
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
String text = "menu click... should be implemented";
Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG).show();
// You should reset item counter
mDrawer.closeDrawer(mDrawerList);
}
}
}
文件选择器.java
public class FileChooser extends Fragment{
private File currentDir;
public FileChooser() {};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.file_view, container, false);
currentDir = new File(Environment.getExternalStorageDirectory().getPath());
FileList flist = new FileList();
flist.fill(currentDir);
return rootView;
}
/*
* Method to fill the current layout with files and folders from the external directory
*
* @params: Path for the SD Card
*/
public class FileList extends ListActivity{
private File currentDir;
private FileArrayAdapter adapter;
void fill(File f)
{
File[]dirs = f.listFiles();
this.setTitle(f.getName());
List<Item>dir = new ArrayList<Item>();
List<Item>fls = new ArrayList<Item>();
try{
for(File ff: dirs)
{
Date lastModDate = new Date(ff.lastModified());
DateFormat formater = DateFormat.getDateTimeInstance();
String date_modify = formater.format(lastModDate);
if(ff.isDirectory()){
File[] fbuf = ff.listFiles();
int buf = 0;
if(fbuf != null){
buf = fbuf.length;
}
else buf = 0;
String num_item = String.valueOf(buf);
if(buf == 0) num_item = num_item + " item";
else num_item = num_item + " items";
//String formated = lastModDate.toString();
dir.add(new Item(ff.getName(),num_item,date_modify,ff.getAbsolutePath(),"directory_icon"));
}
else
{
fls.add(new Item(ff.getName(),ff.length() + " Byte", date_modify, ff.getAbsolutePath(),"file_icon"));
}
}
}catch(Exception e)
{
}
Collections.sort(dir);
Collections.sort(fls);
dir.addAll(fls);
if(!f.getName().equalsIgnoreCase(Environment.getExternalStorageDirectory().getName()))
dir.add(0,new Item("..","Parent Directory","",f.getParent(),"directory_up"));
adapter = new FileArrayAdapter(FileList.this,R.layout.file_view,dir);
this.setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Item o = adapter.getItem(position);
if(o.getImage().equalsIgnoreCase("directory_icon")||o.getImage().equalsIgnoreCase("directory_up")){
currentDir = new File(o.getPath());
fill(currentDir);
}
else
{
onFileClick(o);
}
}
private void onFileClick(Item o)
{
Toast.makeText(this, "Folder Clicked: "+ currentDir, Toast.LENGTH_SHORT).show();
}
}
}
FileArrayAdapter.java
public class FileArrayAdapter extends ArrayAdapter<Item>{
private Context c;
private int id;
private List<Item>items;
public FileArrayAdapter(Context context, int textViewResourceId,
List<Item> objects) {
super(context, textViewResourceId, objects);
c = context;
id = textViewResourceId;
items = objects;
}
public Item getItem(int i)
{
return items.get(i);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(id, null);
}
/* create a new view of my layout and inflate it in the row */
//convertView = ( RelativeLayout ) inflater.inflate( resource, null );
final Item o = items.get(position);
if (o != null) {
TextView t1 = (TextView) v.findViewById(R.id.TextView01);
TextView t2 = (TextView) v.findViewById(R.id.TextView02);
TextView t3 = (TextView) v.findViewById(R.id.TextViewDate);
/* Take the ImageView from layout and set the city's image */
ImageView imageCity = (ImageView) v.findViewById(R.id.fd_Icon1);
String uri = "drawable/" + o.getImage();
int imageResource = c.getResources().getIdentifier(uri, null, c.getPackageName());
Drawable image = c.getResources().getDrawable(imageResource);
imageCity.setImageDrawable(image);
if(t1!=null)
t1.setText(o.getName());
if(t2!=null)
t2.setText(o.getData());
if(t3!=null)
t3.setText(o.getDate());
}
return v;
}
}
日志猫
11-25 11:48:33.382: E/AndroidRuntime(8819): FATAL EXCEPTION: main
11-25 11:48:33.382: E/AndroidRuntime(8819): Process: it.gmariotti.android.example.navigationdrawer, PID: 8819
11-25 11:48:33.382: E/AndroidRuntime(8819): java.lang.RuntimeException: Unable to start activity ComponentInfo{it.gmariotti.android.example.navigationdrawer/com.tdl.filemannavdrawer.MainActivity}: java.lang.IllegalStateException: System services not available to Activities before onCreate()
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2176)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2226)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.ActivityThread.access$700(ActivityThread.java:135)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1397)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.os.Handler.dispatchMessage(Handler.java:102)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.os.Looper.loop(Looper.java:137)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.ActivityThread.main(ActivityThread.java:4998)
11-25 11:48:33.382: E/AndroidRuntime(8819): at java.lang.reflect.Method.invokeNative(Native Method)
11-25 11:48:33.382: E/AndroidRuntime(8819): at java.lang.reflect.Method.invoke(Method.java:515)
11-25 11:48:33.382: E/AndroidRuntime(8819): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
11-25 11:48:33.382: E/AndroidRuntime(8819): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
11-25 11:48:33.382: E/AndroidRuntime(8819): at dalvik.system.NativeStart.main(Native Method)
11-25 11:48:33.382: E/AndroidRuntime(8819): Caused by: java.lang.IllegalStateException: System services not available to Activities before onCreate()
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.Activity.getSystemService(Activity.java:4531)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.widget.ArrayAdapter.init(ArrayAdapter.java:310)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:153)
11-25 11:48:33.382: E/AndroidRuntime(8819): at com.tdl.filemannavdrawer.FileArrayAdapter.<init>(FileArrayAdapter.java:25)
11-25 11:48:33.382: E/AndroidRuntime(8819): at com.tdl.filemannavdrawer.FileChooser$FileList.fill(FileChooser.java:89)
11-25 11:48:33.382: E/AndroidRuntime(8819): at com.tdl.filemannavdrawer.FileChooser.onCreateView(FileChooser.java:35)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.Fragment.performCreateView(Fragment.java:1700)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.BackStackRecord.run(BackStackRecord.java:684)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.Activity.performStart(Activity.java:5252)
11-25 11:48:33.382: E/AndroidRuntime(8819): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2149)
11-25 11:48:33.382: E/AndroidRuntime(8819): ... 11 more
在 FileChooser.java 中,我在 OnCreate() 中调用了 list()。该实现有什么问题吗?有人有我可以参考的带有导航抽屉的文件管理器的工作示例吗?