代码改变世界

Android小項目之--ListView與ListAcitivity完善論壇管理效果2(附源碼)

2010-06-07 23:34  Terry_龙  阅读(5902)  评论(5编辑  收藏  举报

  ListAcitivity 类型布局用来配置应用程序,主要为显示菜单列表、列表明细项目,假如让程序继承 ListActivity ,可以实现以下的方法:

  1. getListAdapter()  取得目前列表项目的 Adapter
  2. getListView()  取得目前列表的 View
  3. getSelectedItemId()  取得目前 Keypad 所选择的 Item ID
  4. getSlectedItemPosition()  取得目前 KeyPad 所选择的Item 索引值
  5. onContentChanged()  ListAcitivity 列表内容更动事件
  6. onListItemClick(ListView ,View ,int,long)  User在列表项目单击触发事件
  7. onRestoreInstanceState(Bundle)  当还原至此实例状态事件
  8. setListAdapter(ListAdapter)  设置 ListAcitivity 的列表项目
  9. setSelection(int)    设置所选择的项目  

  ListAcitivity 默认并不一定要像继承自 Acitivity一样,必须使用 seContentView 来设置版型 Layout 才能显示页面,ListAcitivity 可以在不必重写 Protected void onCreate(Bundle savedInstanceState)的情况下,直接将列表加载至 ListAcitivity 中,非常便利,常用在如投票选项选择、多个项目列表条列显示、文件资源管理等。

  今天此程序将扩展上篇文章遗留下的问题,完善整个实例的全部功能,需要完成的功能清单如下:

  1. 实例继承自 ListAcitivity 实现功能;
  2. 在另外一个类里面实现 BaseAdapter 重写它四个方法;
  3. 得到 ListView 控件里面包含所有控件各自的事件,并为其设置事件监听器;
  4. 长按时如何得到所触发的项,并进行相应的操作,实现长按事件的点击事件。

清单如上,下面是实例运行效果图:



  这篇文章将不介绍如何加载数据给 ListView 具体操作你可以参考我这篇文章:http://www.cnblogs.com/TerryBlog/archive/2010/06/05/1752325.html,下面正式进入代码片段,由于代码量相对比较大,这里就不全部发出代码,感兴趣的朋友可以到下面附件下载。
  问题处理:
  1. 继承 ListAcitivity 之后,我们main.xml将不可以再放任何控件,如果想再添加控件进行操作,可以自己写扩展 XML。因为继承了ListAcitivity 就可以直接在初始化时为调用
    void android.app.ListActivity.setListAdapter(ListAdapter adapter)

    public void setListAdapter (ListAdapter adapter) 
    Since: API Level 
    1 
    Provide the cursor 
    for the list view. 

    此方法,参数为ListAdapter,上篇我们是利用自己加载的 SimpleAdapter 的适配器做数据源,本篇因为继承了 ListAcitivity 所以数据源我们可以这样写,重写 BaseAdapter ,具体看问题2;

  2. 重写 BaseAdapter 代码如下:

    代码
    @Override
        
    public int getCount() {
            
    // TODO Auto-generated method stub
            return listitem.size();
        }

        @Override
        
    public Object getItem(int arg0) {
            
    // TODO Auto-generated method stub
            return listitem.get(arg0);
        }

        @Override
        
    public long getItemId(int arg0) {
            
    // TODO Auto-generated method stub
            return arg0;
        }

        @Override
        
    public View getView(int arg0, View arg1, ViewGroup arg2) {
            
    // TODO Auto-generated method stub
            final ViewHolder myViewHolder;
            
    if(arg1==null)
            {
                
                arg1
    =myInflater.inflate(R.layout.listview_row, null);
                myViewHolder
    =new ViewHolder();
            
                ViewHolder.my_TextView
    =(TextView)arg1.findViewById(R.id.topTextView);
                ViewHolder.my_Button
    =(Button)arg1.findViewById(R.id.Button01);
                
                arg1.setTag(myViewHolder);
                
            }
            
    else
            {
                myViewHolder
    =(ViewHolder)arg1.getTag();
            }
            ViewHolder.my_TextView.setText(listitem.get(arg0).get(
    "itemText").toString());
            ViewHolder.my_Button.setText(listitem.get(arg0).get(
    "buttonText").toString());
            ViewHolder.my_Button.setOnClickListener(
    new OnClickListener() {
                
                @Override
                
    public void onClick(View v) {
                    RelativeLayout rl 
    = (RelativeLayout)v.getParent();
                    
    final TextView subView = (TextView)rl.getChildAt(1);
                    
    // TODO Auto-generated method stub
                    new AlertDialog.Builder(myContext)
                    .setTitle(R.string.confirm)
                    .setMessage(R.string.top)
                    .setPositiveButton(R.string.ok, 
    new DialogInterface.OnClickListener() {
                        
                        @Override
                        
    public void onClick(DialogInterface dialog, int which) {
                            
    // TODO Auto-generated method stub
                            subView.setTextColor(Color.RED);
                        }
                    })
                    .setNeutralButton(R.string.cancel, 
    null)
                    .show();
                }
            });
            
            ViewHolder.my_TextView.setOnCreateContextMenuListener(
    new OnCreateContextMenuListener() {
                
                @Override
                
    public void onCreateContextMenu(ContextMenu menu, View v,
                        ContextMenuInfo menuInfo) {
                    
    // TODO Auto-generated method stub
                    ListViewActivity lv=(ListViewActivity)myContext;
                    lv.myRelative
    =(RelativeLayout)v.getParent();
                    menu.setHeaderIcon(R.drawable.icon);
                    menu.setHeaderTitle(ViewHolder.my_TextView.getText());
                    menu.add(
    100"高亮");
                    menu.add(
    010"置頂"); 
                }
        
            
            });
            
             
            
    return arg1;
        }

     

    构造函数为引入上篇上下文和数据;

    方法一:获取数据源的总列数;
    方法二:通过参数值获取每个集合的项;
    方法三:获得当前项的索引;
    方法四:返回我们需要的View。
  3. LayoutInflater 的使用,LayoutInflater 这个类非常有用,它的作用类似于 findViewById() ,不同点的是 LayoutInflater 是用来找layout xml 布局文件,并且实例化!而 findViewById() 是找具体 xml 下的具体 widget 控件(如: Button , TextView 等)。

    一般来讲,我们用 LayoutInflater 做一件事:inflateinflate这个方法总共有四种形式,目的都是把xml 表述的layout 转化为ViewThis class is used to instantiate layout XML file into its corresponding View objects . It is never be used directly -- use getLayoutInflater() or getSystemService(String)getLayoutInflater() or getSystemService(String) to retrieve a standard LayoutInflater instance that is already hooked up to the current context and correctly configured for the device you are running on
      A. Context.public abstract Object getSystemService (String name) Return the handle to a system-level service by name. The class of the returned object varies by the requested name. 具体参见文档。
      B.种获得LayoutInflater 的方法

        (1)通过SystemService获得LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        (2)从给定的context中获取
      C. LayoutInflater.inflate()
        Layout文件转换为View,顾名思义,专门供Layout使用的Inflater。虽然Layout也是View的子类,但在android中    如果想将xml中的Layout转换为View放入.java代码中操作,只能通过Inflater,而不能通过findViewById()。
      
    D.findViewById() 有两种形式
          R.layout.xx 是引用res/layout/xx.xml的布局文件(inflate方法),R.id.xx是引用布局文件里面的组件,组件的idxx...(findViewById方法)。看看R.java配置文件吧,R对文件分类管理,多写几个layout.xml后你会发现,所有的组件id都能用R.id.xx来查看,但是组件不在setContentView()里面的layout中就无法使用,Activity.findViewById()会出现空指针异常
    详细使用步骤如下:

private LayoutInflater myInflater=null;

 

 之后我们在

public View getView(int arg0, View arg1, ViewGroup arg2) {

 

方法里面调用方法参数View arg1使用

arg1=myInflater.inflate(R.layout.listview_row, null);

 

 

即可得到相应的 View ,得到 View 之后即可以轻松的使用 findViewById() 方法操作控件,并为且设置对应的监听事件。

4.上篇文章我们留下了一个问题,即如何在长按时能够得到长按的某一项,并得到项操作相应的业务逻辑,本篇将完成此功能。在继承 ListAcitivity 类里声明 public RelativeLayout myRelative; 此相对布局控件来源于布局XML的布局控件,之后在设置长按事件的处理函数中进行如下操作:

ListViewActivity lv=(ListViewActivity)myContext;
                lv.myRelative
=(RelativeLayout)v.getParent();

 

上述代码为,将上下文引入,得到上下文声明的相对布局控件,因为方法的参数View 为相应的点击控件,为了得到布局控件,使用View.getParent() 得到相对的父控件,这里我用的是 TextView 它放在 RelativeLayout 此控件的下方法,故为getParent(),得到每次点击项的布局控件后,再重写onContextItemSelected ,代码如下:

代码
public boolean onContextItemSelected(MenuItem item) {
        
// TODO Auto-generated method stub
        switch (item.getItemId()) {
        
case 0:
            ViewHolder.my_TextView
=(TextView)myRelative.getChildAt(1);
            ViewHolder.my_TextView.setBackgroundColor(Color.BLUE);
            
return true;
        
case 1:
            ViewHolder.my_TextView
=(TextView)myRelative.getChildAt(1);
            Toast.makeText(
this, ViewHolder.my_TextView.getText()+"添加置頂效果"1000).show();
            
return true;
         
        }
        
return super.onContextItemSelected(item);
    }

 

 

这里有必要解释一下,这一段实现菜单的选择功能,应该放在 Activity 代码类里面,因为上面我们通过在此类中声明一个 RelativeLayout 然后当点击时我们即为它赋值,点击完某一菜单按钮后即返回 Activity 页面,得到布局,我们在这里要实现的只有通过操作相对布局控件里面包含的控件然后进行操作即可完全实现 这一功能,在布局控件里面找控件可用此方法 getChildAt(int index);注意上面条件分支语句不是跳出而是返回一个真。

到此,此功能己经得到实现,在此要感谢以下两人对我的帮助:QQ:182041935---QQ120460734

 

源码下载:/Files/TerryBlog/listViewDemo.rar

 

如果你有什么疑问或者建议 你可以  QQ285735942 Email:terryyhl@gmail.com