动态显示文件名之ListView



    1. 添加listView控件

     在上一篇文章中新增了一个layout:/filedel/res/layout/file_display.xml,现在,在此layout中增加一个ListView控件

    

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

   2. 关联View与数据

     在上一篇中新增加了类,com.example.filedel.FileDispActivity ,现在,在此类的OnCreate函数中增加代码

   

        ListView lv;        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.file_display);

        File fileDir = getFilesDir();
       /* 获得路径下面的文件名称,放到String数组中,目前怎么对String数组进行操作,比如判断是否为空,长度及输出数组的值 */
       String[] fileList = fileDir.list(); 

       /*得到ListView对象的引用*/
       lv = (ListView) findViewById(R.id.listView1);
       /*为ListView设置Adapter来绑定数据*/ 
       lv.setAdapter(new ArrayAdapter<String>(this, 
                   android.R.layout.simple_list_item_multiple_choice, fileList));

             此段代码中出现了一个新的名词:Adapter。Adapter用于链接listview(View)与数据的桥梁。这个桥梁如何创建呢?一个View是如何与不同的数据源进行关联的呢?

            代码中通过new ArrayAdapter,创建了一个adapter的对象。通过setAdapter建立了View,adapter及数据之间的关系。adapter对象创建时,调用的构造函数的第二个参数“android.R.layout.simple_list_item_multiple_choice”指明了 此ListView的layout,目前Android支持几种listview的layout,也可以自己定义;第三个参数即为数据。

            此处使用了最简单的adapter形式:

            ArrayAdapter<T>      用来绑定一个数组形式的数据源,支持泛型操作

      3. 设置listview的选择模式

         有如下四种模式:

/**
 * Normal list that does not indicate choices
 */
public static final int CHOICE_MODE_NONE = 0;
/**
 * The list allows up to one choice
 */
public static final int CHOICE_MODE_SINGLE = 1;
/**
 * The list allows multiple choices
 */
public static final int CHOICE_MODE_MULTIPLE = 2;
/**
 * The list allows multiple choices in a modal selection mode
 */
<pre name="code" class="java">public static final int CHOICE_MODE_MULTIPLE_MODAL = 3;

    通过如下代码设置,此处代码设置了多选框的模式, 

  

  lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

    4. 响应选择事件

      这里分为两步。一种情况为选择一个处理一个;另外一种情况为选择多个,然后统一处理。

       短按事件处理

       针对第一种情况,增加如下接口响应某一项的点击选择;

     

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> arg0, View arg1,
						int arg2, long arg3) {
					// TODO Auto-generated method stub
					setTitle("test ok");
				}
	        	 
			});

      长按事件处理

      针对第二种情况:需要首先屏蔽掉第一种情况涉及到的onItemClick事件,使用CHOICE_MODE_MULTIPLE_MODAL模式,在此模式下要启用多选操作,有两种办法:

  (1)长按某个item(例子:android的文件管理器,点击目录就会进入目录的下一级;而长按目录,则此目录后面会出现一个多选框,并选择上) ;长按时,需要实现对应的响应函数,否则程序会出现异常。长按时,增加如下代码,则程序不会出现异常:

        

    mCallback = new ModeCallback();  
    lv.setMultiChoiceModeListener(mCallback);  /* 注册多选模式的回调函数,当长按触发多选模式时就会进入此类中的各个函数 */

      类中的函数有如下五个: 长按某个item时,onCreateActionMode函数首先被调用,默认在页面顶端会创建新的视图,可以在此函数中增加创建 Menu的代码。

     

class ModeCallback implements ListView.MultiChoiceModeListener{

	@Override
	public boolean onActionItemClicked(ActionMode arg0, MenuItem arg1) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onCreateActionMode(ActionMode arg0, Menu arg1) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onDestroyActionMode(ActionMode arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onItemCheckedStateChanged(ActionMode arg0, int arg1, long arg2,
			boolean arg3) {
		// TODO Auto-generated method stub
		
	}
}


      长按时,创建Menu:

   

@Override
	public boolean onCreateActionMode(ActionMode arg0, Menu arg1) {
		// TODO Auto-generated method stub
		MenuInflater inflater = arg0.getMenuInflater();  /*arg0 代表的是新的View,从arg0里面提取Menu所在的配置 */
	        inflater.inflate(R.menu.contextmenu, arg1);  /* 将预定义的menu配置文件和具体的menu菜单位置进行配对。菜单的位置目前默认是在手机屏幕的上方 */
                return true;  
	}

   针对选择的项目:下面这个函数可以获取哪个item被选择了,经过测试,参数arg1 arg2都表示item的编号,从0开始,这两个参数的差异是什么?
  
@Override
	public void onItemCheckedStateChanged(ActionMode arg0, int arg1, long arg2,
			boolean arg3) {
		// TODO Auto-generated method stub
		
	}
    itemclicked,表示在create中的 ”菜单项“ 被选择时,触发的操作:
@Override
	public boolean onActionItemClicked(ActionMode arg0, MenuItem arg1) {
		// TODO Auto-generated method stub
		return false;
	}

      此处,将上述新定义的类
class ModeCallback implements ListView.MultiChoiceModeListener{

     作为类com.example.filedel.FileDispActivity的一个内部类,以便访问com.example.filedel.FileDispActivity的变量及使用相关的接口。

    最终的代码如下:实现了长按后,进入ActionMode,而后选择几个项后,程序会记录,而后在actionmode中的菜单项中针对此菜单项进行文件删除操作。目前代码存在的问题:选择的项和实际删除的文件项的对应关系,此种情况可能需要修改setAdapter时的数据来源。

   

public class FileDispActivity extends Activity{
	File fileDir ;
    /* 获得路径下面的文件名称,放到String数组中,目前怎么对String数组进行操作,比如判断是否为空,长度及输出数组的值 */
    String[] fileList ;
    File[]   fileObj;
    int []   selected;
	 @Override
	    protected void onCreate(Bundle savedInstanceState) {		 
		
		    ListView lv;
		    ModeCallback mCallback;   
		    
	        
		  	super.onCreate(savedInstanceState);
	        setContentView(R.layout.file_display);
	       
	        fileDir = getFilesDir();
	        fileList = fileDir.list();
	        fileObj = fileDir.listFiles();
	        selected=new int[20];
	        lv = (ListView) findViewById(R.id.listView1);//得到ListView对象的引用 /*为ListView设置Adapter来绑定数据*/ 

	        lv.setAdapter(new ArrayAdapter<String>(this,
	                        android.R.layout.simple_list_item_multiple_choice, fileList));
	        lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
	        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> arg0, View arg1,
						int arg2, long arg3) {
					// TODO Auto-generated method stub
					setTitle("test ok"+arg2);
					
				}
	        	 
			});
	        mCallback = new ModeCallback();
	        lv.setMultiChoiceModeListener(mCallback);
	        
	 }
	 private class ModeCallback implements ListView.MultiChoiceModeListener{
			
			private View mMultiSelectActionBarView;
		    private TextView mSelectedCount;
			/** 
		     * 单击ActionMode的菜单项会调用此方法。 
		     */  
			@Override
			public boolean onActionItemClicked(ActionMode arg0, MenuItem arg1) {
				// TODO Auto-generated method stub
				/* 针对出现的menu菜单的操作,选择下menu菜单,则会运行此函数 */
				int i=0;
				int filenum =0;
				arg1.getItemId();
				for(i=0;i<fileObj.length;i++)
				{
					if(fileObj[i].exists())
					{
						filenum++;
						
					}
				}
				arg0.setTitle("file num: "+filenum);
				for(i=0;i<fileObj.length;i++)
				{
					if (selected[i]==1)      /*根据是否选择了,进行文件的删除 */
					{
						fileObj[i].delete();
					}
				}
				filenum=0;
				for(i=0;i<fileObj.length;i++)
				{
					if(fileObj[i].exists())
					{
						filenum++;
						
					}
				}
				arg0.setTitle("file num: "+filenum);
				return true;
			}
			  /** 
		     * 创建ActionMode,即:长按ListView以后会出现蒙板效果,这个蒙板就是ActionMode, 
		     * 可以在上面添加菜单,快捷按钮等。 
		     */  
			@Override
			public boolean onCreateActionMode(ActionMode arg0, Menu arg1) {
				// TODO Auto-generated method stub
				MenuInflater inflater = arg0.getMenuInflater();
			    inflater.inflate(R.menu.contextmenu, arg1);			    
		        return true;
		        
			}

			@Override
			public void onDestroyActionMode(ActionMode arg0) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
				// TODO Auto-generated method stub
				return false;
			}
			/** 
		    * 在选择ListView的一个条目时会触发。  
		    */  
			@Override
			public void onItemCheckedStateChanged(ActionMode arg0, int arg1, long arg2,
					boolean arg3) {
				// TODO Auto-generated method stub
				if (fileObj[arg1].exists())
				{
					arg0.setTitle(fileList[ arg1]);
					selected[ arg1]=1;   /* 记录哪个选择项被选择了! */
				}	
				else
				{
					arg0.setTitle("delete now");
				}
				
			}
		}

}

       在上述代码,针对 “菜单项” 的处理函数中增加代码,让用户确认是否需要真的删除

     

new AlertDialog.Builder(FileDispActivity.this)   
			    .setTitle("确认")  
			    .setMessage("删除文件?")  
			    .setPositiveButton("是", new DialogInterface.OnClickListener(){

					@Override
					public void onClick(DialogInterface arg0, int arg1) {
						// TODO Auto-generated method stub
						int i=0;
						for(i=0;i<allFile.length;i++)
						{
							if (selected[i]==1)
							{
								allFile[i].delete();
							}
						}
					}
			    	
			    })  
			    .setNegativeButton("否", new DialogInterface.OnClickListener(){

					@Override
					public void onClick(DialogInterface arg0, int arg1) {
						// TODO Auto-generated method stub
						
					}
			    	
			    })  
			    .show();  


     (2)主动调用ListView的setItemChecked(int position, boolean value)方法选中一个item。



  参考资料:

 1. listview布局说明 几种布局及自定义布局

 2.  ListView 。listview说明

 3. listmode  list mode

 4. api    api说明

 5. java内部类:介绍了java内部类使用方法及分类。本文中涉及到了成员内部类的使用。成员内部类引用外部类的方法及变量函数声明时的注意事项   java内部类

 6. 获取内部存储设备的挂载的路径,由于各个厂商定义不同,Environment.getExternalStorageDirectory() 接口并不能正确获取 内部卡的挂载节点,此链接提供了扫描/etc/下配置文件的方式来获得挂载点的方法 获取内部存储设备路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

proware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值