Android开发 - 创建用户界面

关键字:merge标签、include标签、ViewStub、Lint工具、Fragment、Animations、Adapter

 

  • 使用视图和布局
  • 理解Fragment
  • 优化布局
  • 创建分辨率无关的用户界面
  • 扩展、分组、创建和使用视图
  • 使用适配器将数据绑定到视图

 

将用户界面分配给Activity

setContentView

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

通过使用findViewById来得到布局内每个视图的引用

EditText editText = (EditText)findViewById(R.id.editText);

当然也可以使用传统的代码方式来构建UI。

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        TextView myTextView = new TextView(this);
        setContentView(myTextView);

        myTextView.setText("Hello, Android");
    }
}

定义布局

在XML中实现布局可以把表示层从视图、Fragment和Activity代码中分离出来。它也可以创建支持特定硬件的、无需更改代码就可以动态地加载的变体。

 

优化布局

填充布局是一个开销巨大的过程;每个额外的嵌套布局和它所包含的View,都直接影响应用程序的性能和响应能力。

为了使应用程序流畅地运行和快速地响应,重要的是尽可能地保持布局的简单和避免出现因为相对较小UI的变动而完全填充新的布局的情况。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
   android:text="@string/hello" />
</FrameLayout>

上面代码中的FrameLayout被添加到父容器时,就会变成一个冗余。因为layout_width和layout_height都被设置为MATCH_PARENT,这是没有意义的。

这时最好的方案是选择merge标签。

merge标签

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
   android:text="@string/hello" />
</merge>

当包含merge标签的布局被添加到另一个布局时,该布局的merge节点会被删除,而该布局的子View会被直接添加到新的父布局中。

include标签

merge标签结合include标签一起使用尤其有用,include标签是用来把一个布局的内容插入到另一个布局中。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" >
  <include android:id="@+id/my_action_bar"
                layout="@layout/actionbar"/>
  <include android:id="@+id/my_image_text_layout"
                layout="@layout/image_text_layout"/>
</LinearLayout>    

避免使用过多的View

填充每个额外的View都需要花费时间和资源。为了最大限度地提高应用程序的速度和响应能力,布局包含的View个数不应该超过80。如果超过这个限制,填充布局花费的时间将成为一个显著的问题。

要想在复杂的布局内填充的View的数量越少,可以使用ViewStub。

ViewStub的工作原理就像是一个延时填充的include标签 - 一个stub代表了在父布局中指定的(多个)子View - 但只有显式地调用inflate()方法或者被置为可见的时候,这个stub才会被填充。

 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/myListView"></ListView>
    
    <ViewStub
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:layout_gravity="bottom"
        android:id="@+id/download_progress_panel_stub"
        android:layout="@layout/progress_overlay_panel"
        android:inflatedId="@+id/download_progress_panel"/>
</FrameLayout>
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //查找stub
        View stub = findViewById(R.id.download_progress_panel_stub);

        //将其设置为可见,以填充子布局
        stub.setVisibility(View.VISIBLE);

        //查找以填充的stub布局的根节点
        View downloadProgressPanel = findViewById(R.id.download_progress_panel);
    }
}

 

使用Lint工具来分析布局

http://tools.android.com/tips/lint

 

ToDoList示例

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <EditText
    android:id="@+id/myEditText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/addItemHint"
    android:contentDescription="@string/addItemContentDescription"
  />
  <ListView
    android:id="@+id/myListView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
  />
</LinearLayout>
main.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">ToDoList</string>
  <string name="addItemHint">New To Do Item</string>
  <string name="addItemContentDescription">New To Do Item</string>
</resources>
strings.xml
public class ToDoListActivity extends Activity {
  
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  
    // Inflate your View
    setContentView(R.layout.main);
  
    // Get references to UI widgets
    ListView myListView = (ListView)findViewById(R.id.myListView);
    final EditText myEditText = (EditText)findViewById(R.id.myEditText);
    
    // Create the Array List of to do items
    final ArrayList<String> todoItems = new ArrayList<String>();
   
    // Create the Array Adapter to bind the array to the List View
    final ArrayAdapter<String> aa;
   
    aa = new ArrayAdapter<String>(this,
                                  android.R.layout.simple_list_item_1,
                                  todoItems);
   
    // Bind the Array Adapter to the List View
    myListView.setAdapter(aa);
  
    myEditText.setOnKeyListener(new View.OnKeyListener() {
      public boolean onKey(View v, int keyCode, KeyEvent event) { 
        if (event.getAction() == KeyEvent.ACTION_DOWN)
          if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER) ||
              (keyCode == KeyEvent.KEYCODE_ENTER)) {
            todoItems.add(0, myEditText.getText().toString());
            aa.notifyDataSetChanged();
            myEditText.setText("");
            return true;
          }
        return false;
      }
    });

  }

}
ToDoListActivity.java

 

Fragment

Fragment允许将Activity拆分成多个完全独立封装的可重用的组件,每个组件有它自己的生命周期和UI布局。Fragment最大的优点是可以为不同屏幕大小的设备创建动态灵活的UI。

创建新的Fragment

大多数情况下,需要为Fragment分配一个UI。也可以为一个Activity创建一个没有任何UI但提供后台行为的Fragment。

Fragment如果需要UI,可以重写onCreateView方法来填充并返回所需要的View层次。

public class MySkeletonFragment extends Fragment {

  @Override
  public View onCreateView(LayoutInflater inflater, 
                           ViewGroup container,
                           Bundle savedInstanceState) {
    // 创建或者填充Fragment的UI,并且返回它
    // 如果这个Fragment没有UI,返回null
    return inflater.inflate(R.layout.my_fragment, container, false);
  }
}

和Activity不同,Fragment不需要在manifest.xml中注册。这是因为Fragment只有嵌入到一个Activity时,它才能够存在,它的生命周期也依赖于它所嵌入的Activity。

Fragment的生命周期

/**
 * Listing 4-4: Fragment skeleton code
 * Listing 4-5: Fragment lifecycle event handlers
 */
package com.paad.fragments;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MySkeletonFragment extends Fragment {

  // 调用该方法时Fragment会被连接到它的父Activity上。
  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
    // 获取对父Activity的引用
  }

  // 调用该方法来进行Fragment的创建
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 初始化Fragment
  }

  // 一旦Fragment已被创建,要创建它自己的用户界面时调用该方法
  @Override
  public View onCreateView(LayoutInflater inflater, 
                           ViewGroup container,
                           Bundle savedInstanceState) {
    // 创建或者填充Fragment的UI,并返回它
    // 如果这个Fragment没有UI,那么返回null
    return inflater.inflate(R.layout.my_fragment, container, false);
  }

  // 一旦父Activity和Fragment的UI已被创建,则调用该方法
  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // 完成Fragment的初始化 - 尤其是那些父Activity被初始化完成后或者Fragment的View被完全填充后才能做的事情
  }

  // 在可见生命周期的开始时被调用
  @Override
  public void onStart(){
    super.onStart();
    // 应用所有需要的UI变化,现在Fragment是可见的
  }

  // 在活动生命周期的开始时被调用
  @Override
  public void onResume(){
    super.onResume();
    // 回复所有暂停的Fragment需要的UI更新,线程或者进程,但在非活动状态它是暂停的
  }

  // 在活动生命周期结束时被调用
  @Override
  public void onPause(){
    // 当Activity不是活动的的前台Activity时,需要暂停UI的更新、挂起线程或者暂停那些不需要更新的CPU的集中处理
    // 由于调用这个方法后,进程可能被终止,所以要保存所有的编辑和状态改变信息
    super.onPause();
  }

  // 在活动生命周期结束时,调用该方法保存UI的状态变化
  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    // 将UI的状态改变信息保存到savedInstanceState中
    // 这个Bundle会被传递到onCreate、onCreateView和onActivityCreate(如果它的父Activity被终止并且重新启动)方法中
    super.onSaveInstanceState(savedInstanceState);
  }

  // 在可见生命周期结束时调用该方法
  @Override
  public void onStop(){
    // 当Fragment不可见时,暂停其余的UI更新、挂起线程或者暂停不再需要的处理
    super.onStop();
  }

  // 当Fragment的View被分离时,调用该方法
  @Override
  public void onDestroyView() {
    // 清除资源相关的View
    super.onDestroyView();
  }

  // 在整个生命周期结束时调用该方法
  @Override
  public void onDestroy(){
    // 清除所有的资源,包括结束线程和关闭数据库连接等
    super.onDestroy();
  }

  // 当Fragment从它的父Activity上分离时,调用该方法
  @Override
  public void onDetach() {
    super.onDetach();
  }
}

从父Activity中绑定和分离Fragment

Fragment完整的生命周期开始于绑定到它的父Activity,结束于从父Activity上分离。通过分别调用onAttach和onDetach来表示这些事件。

在Fragment/Activity被暂停后,由于任何其他处理程序都可以被调用,可能就会出现它的父Activity进程没有完成它的全部生命周期被终止从而导致onDetach不会被调用的情况。

创建和销毁Fragment
已创建Fragment的生命周期存在于首次对onCreate的调用和最终对onDestroy的调用的期间。因为对Activity的进程来说,再没有相应的onDestroy方法被调用而被终止的情况很常见,所以Fragment不能依赖触发onDestroy方法来销毁它。
与Activity一样,应该使用onCreate方法来初始化Fragment。在Fragment生命周期内创建的任何类作用于对象,最好确保它们只被创建一次。
与Activity不同,Fragment的UI不在onCreate方法中初始化。

创建和销毁用户界面
Fragment的UI是在onCreateView和onDestroyView中初始化和销毁。
使用onCreateView方法来初始化Fragment:填充UI、获取它所包含的View的引用,然后创建所需的任何的Service和Timer。
一旦已经填充好了View层次,该View应该从这个处理程序返回:
return inflater.inflate(R.layout.m_fragment, container, false);
如果Fragment需要和它的父Activity的UI交互,需要一直等到onActivityCreate事件被触发。该事件被触发意味着Fragment所在的Activity已经完成了初始化并且它的UI也已经完全构建好了。

Fragment状态
和Activity一样,当Fragment所属的Activity处在前台并拥有焦点时,这些Fragment也是活动的。当Activity被暂停或停止,它所包含的Fragment也会被暂停或停止。一个非活动的Activity包含的Fragment也是非活动的。当Activity最终被销毁时,它所包含的每一个Fragment同样也会被销毁。
当Android内存管理器通过随即关闭一些应用程序来释放资源时,那些Activity所包含的Fragment也同样会被销毁。
当Fragment暂停或停止时,保存所有的UI状态和持久化所有的数据是非常重要的。和Activity一样,当一个Fragment再次变为活动状态时,它应该恢复之前保存的状态。

Fragment Manager介绍
每一个Activity都包含一个Fragment Manager来管理它所包含的Fragment。可以通过getFragmentManager方法来访问Fragment Manager:

FragmentManager fm = getFragmentManager();

Fragment Manager提供了很多方法来访问当前添加到Activity上的Fragment,通过执行Fragment Transaction来添加、删除和替换Fragment。

向Activity中添加Fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <fragment android:name="com.paad.weatherstation.MyListFragment"
    android:id="@+id/my_list_fragment"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="1"
  />
  <fragment android:name="com.paad.weatherstation.DetailsFragment"
    android:id="@+id/details_fragment"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="3"
  />
</LinearLayout>

当使用Fragment基于不同屏幕尺寸来定义一系列静态布局时,这个技术是行之有效的。
如果打算在运行时通过添加、删除或者替换Fragment的方式来动态地修改布局,更好的方法是基于当前的应用程序状态使用容器View来创建布局,Fragment可以在运行时放入到一个容器View内。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <FrameLayout
    android:id="@+id/ui_container"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="1"
  />
  <FrameLayout
    android:id="@+id/details_container"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="3"
  />
</LinearLayout> 

然后,需要在Activity的onCreate处理程序中使用Fragment Transaction来创建相应的Fragment,并把它添加到对应的父容器中。

FragmentTransaction ft = fm.beginTransaction(); 
ft.add(R.id.details_container, new DetailsFragment());
ft.add(R.id.ui_container, new MyListFragment());
ft.commit();

 

使用Fragment Transaction
在运行时,Fragment Transaction可以用来在一个Activity内添加、删除和替换Fragment。使用Fragment Transaction,可以让布局称为动态的。它们会根据与用户的交互和应用程序的状态进行自适应和改变。
一个新的Fragment Transaction是通过使用Activity的Fragment Manager中的beginTransaction方法创建的。在设置显示动画之前,可以根据要求使用add、remove和replace方法来修改布局,并设置适当的back栈行为。当准备执行改变时,调用commit方法将事物添加到UI队列。

FragmentTransaction ft = fm.beginTransaction(); 
ft.add(R.id.details_container, new DetailsFragment());
ft.add(R.id.ui_container, new MyListFragment());
ft.commit();

添加、删除和替换Fragment
添加一个新的UIFragment时,需要指定要添加的Fragment实例和将要放置它的容器View。另外,还可以为这个Fragment制定一个tag标识,后面通过这个标识,可以使用findFragmentByTag方法找到对应的Fragment。

FragmentTransaction ft = fm.beginTransaction(); 
ft.add(R.id.ui_container, new MyListFragment());
ft.commit();

要想删除一个Fragment,首先需要找到对这个Fragment的引用,通常是通过Fragment Manager的findFragmentById或者findFragmentByTag来实现。然后,把找到的Fragment实例作为参数传给Fragment Transaction的remove方法。

FragmentTransaction ft = fm.beginTransaction(); 
DetailsFragment detailsFragment = (DetailsFragment)fm.findFragmentById(R.id.details_container);
ft.remove(detailsFragment);
ft.commit();

还可以把一个Fragment替换成另一个。可以使用replace方法,指定要替换的Fragment的父容器ID、一个替换它的新Fragment和新Fragment的tag标识(可选)。

FragmentTransaction ft = fm.beginTransaction(); 
ft.replace(R.id.details_container, new DetailsFragment(selected_index));
ft.commit();

使用Fragment Manager查找Fragment
要想在Activity中查找Fragment,可以使用Fragment Manager的findFragmentById方法来实现。如果是通过XML布局方式把Fragment加入到Activity中的,可以使用这个Fragment的资源标识符。

detailsFragment = (DetailsFragment)fm.findFragmentById(R.id.details_container);

如果已经通过Fragment Transaction添加了一个Fragment,应该把容器View的资源标识符指定给添加了想要查找的Fragment。另外,还可以通过使用findFragmentByTag来查找在Fragment Transaction中指定了tag标识的Fragment。

detailsFragment = (DetailsFragment)fm.findFragmentByTag(MY_FRAGMENT_TAG);

 

使用Fragment填充动态的Activity布局
如果希望在运行时动态地改变Fragment的结构和布局,最好在XML文件的布局中只定义父容器,并在运行时使用Fragment Transaction来单独填充它,从而当因配置改变(如屏幕旋转)而引起的UI重新构建时,能够保持一致性。

public class MyFragmentActivity extends Activity {

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // 填充包含Fragment容器的布局
    setContentView(R.layout.fragment_container_layout);
    
    FragmentManager fm = getFragmentManager();

    // 检查该布Fragment back栈是否被填充,如果没有,创建并填充布局。
    DetailsFragment detailsFragment = 
      (DetailsFragment)fm.findFragmentById(R.id.details_container);
    
    if (detailsFragment == null) {
       FragmentTransaction ft = fm.beginTransaction(); 
       ft.add(R.id.details_container, new DetailsFragment());
       ft.add(R.id.ui_container, new MyListFragment());
       ft.commit();
     }
  }
}

在一个给定方向的布局中删除一个Fragment容器,只需要简单地将布局定义中该Fragment的visbility属性设置为“gone”即可。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <FrameLayout
    android:id="@+id/ui_container"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="1"
  />
  <FrameLayout
    android:id="@+id/details_container"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="3"
    android:visibility="gone"
  />
</LinearLayout> 

 

Fragment和back栈
Fragment能够创建动态的Activity布局,这些布局可以被修改来使UI发生重大的改变。在某些情况下,这些改变可以被视为一个新的屏幕,在这种情况下,用户可能会理所当然地期望Back按键会返回到前一个布局。同样包括回滚前一个已执行的Fragment Transaction。
想要将Fragment Transaction添加到back栈中,可以在调用commit方法前,在Fragment Transaction中调用addToBackStack方法。

FragmentTransaction ft = fragmentManager.beginTransaction();
ft.add(R.id.ui_container,new MyListFragment());

Fragment fragment = fragmentManager.findFragmentById(R.id.detailsFragment);

ft.remove(fragment);

String tag = null;
ft.addToBackStack(tag);

ft.commit();

当按下Back按键时,之前的Fragment Transaction将会回滚并且UI将返回到之前的布局。


使Fragment Transaction动起来
想要应用众多默认过度动画中的一个,可以对任何Fragment Transaction使用setTransition方法,并传入一个FragmentTransaction.TRANSIT_FRAGMENT_*常量:

fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

也可以通过使用setCustomAnimations方法对Fragment Transaction应用自定义动画。
这个方法接受两个动画XML资源,一个是通过该事务添加到布局的Fragment,另一个是被删除的Fragment。

fragmentTransaction.setCustomAnimations(R.animator.fragment_slide_left_enter,R.animator.fragment_slide_right_exit);

 

Fragment和Activity之间的接口
在任何Fragment中使用getActivity方法来返回它所嵌入的Activity的引用。

TextView textView =(TextView) getActivity().findViewById(R.id.textView);

尽管Fragment可以直接使用主Activity的Fragment Manager进行通信,但是通常最好考虑使用Activity来做媒介。这样会让Fragment尽可能独立和松耦合,而Fragment的职责在于决定Fragment中的一个事件应该如何影响主Activity的整体UI性能下降。
在Fragment需要和它的主Activity共享事件的地方(如提示UI选中),最好在Fragment中创建一个callback接口,而在Activity中实现它。
以下代码在Fragment派生类中定义了一个公共的事件监听接口,通过重写onAttach处理程序用来获得主Activity的引用,并确保主Activity实现了必要的接口。

public class SeasonFragment extends Fragment {

  public interface OnSeasonSelectedListener {
    public void onSeasonSelected(Season season);
  }
    
  private OnSeasonSelectedListener onSeasonSelectedListener;
  private Season currentSeason;

  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
      
    try {
      onSeasonSelectedListener = (OnSeasonSelectedListener)activity;
    } catch (ClassCastException e) {
      throw new ClassCastException(activity.toString() + 
                " must implement OnSeasonSelectedListener");
    }
  }

  private void setSeason(Season season) {
    currentSeason = season;
    onSeasonSelectedListener.onSeasonSelected(season);
  }
  
}

 

没有用户界面的Fragment

也可以创建没有UI的Fragment来提供后台行为,该行为会一直持续到Activity重新启动。
这特别适合于定期和UI交互的后台任务或者当因配置改变而导致的Activity重新启动时,保存状态变得特别重要的场合。
当Fragment的父Activity重新创建时,可以选择使用Fragment的setRetainInstance方法让一个活动的Fragment保留它的实例。在调用该方法后,Fragment的生命周期会改变。
当Activity重新启动时,同一个Fragment的实例会被保留下来,而不是和它的父Activity一起被销毁和重新创建。但Fragment所在的Activity被销毁时,将会收到onDetach事件,之后当新的父Activity实例化后,还会收到onAttach、onCreateView和onActivityCreated事件。
要把没有UI的Fragment加入到Activity中,必须创建一个新的Fragment Transaction,并指定一个tag来标识该Fragment。

 

Adapter
Adapter用来把数据绑定到扩展了AdapterView类的视图组(如ListView或者Gallery)。Adapter负责创建代表所绑定父视图中的低层数据的子视图。
因为Adapter既负责提供数据,有负责创建代表每一个条目的视图,所以Adapter可以从根本上修改它们所绑定的控件的外观和功能。

 

定制ArrayAdapter
默认情况下,ArrayAdapter将使用一个对象数组的每个原色的toString值来填充指定布局中的TextView。

public class MyArrayAdapter extends ArrayAdapter<MyClass> {

  int resource;

  public MyArrayAdapter(Context context,
                         int _resource,
                         List<MyClass> items) {
    super(context, _resource, items);
    resource = _resource;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    // 创建并填充要显示的视图
    LinearLayout newView;

    if (convertView == null) {
      // 如果不是第一次更新,则填充一个新视图
      newView = new LinearLayout(getContext());
      String inflater = Context.LAYOUT_INFLATER_SERVICE;
      LayoutInflater li;
      li = (LayoutInflater)getContext().getSystemService(inflater);
      li.inflate(resource, newView, true);
    } else {
      // 否则更新现有视图
      newView = (LinearLayout)convertView;
    }

    MyClass classInstance = getItem(position);

    // TODO: 从classInstance变量检索要显示的值

    // TODO: 获得对视图的引用来填充布局
    // TODO: 使用对象的属性值填充视图

    return newView;
  }
}

 

使用Adapter绑定数据到视图
要把一个Adapter应用到一个由AdapterView派生的类中,可以调用视图的setAdapter方法,并传递给它一个Adapter实例。

ArrayList<String> myStringArray = new ArrayList<String>();
int layoutID = android.R.layout.simple_list_item_1;

ArrayAdapter<String> myAdapterInstance;
myAdapterInstance = new ArrayAdapter<String>(this, layoutID, myStringArray);

myListView.setAdapter(myAdapterInstance);

使用SimpleCursorAdapter
SimpleCursorAdapter用于将一个Cursor绑定到一个AdapterView,并使用一个布局来定义每个行/条目的UI。每个行的视图的内容使用底层Cursor中对应行的列值进行填充的。
SimpleCursorAdapter是通过传入当前的上下文、用于每个条目的一个布局资源、一个代表要显示的数据的Cursor和两个整数数组进行构建的,这两个数组的其中一个包含了要使用的列(包含源数据),另一个(同样大小的)数组存储资源ID,用于指定布局内的哪些视图应该用来显示相应列的内容。

SimpleCursorAdapter adapter = new SimpleCursorAdapter(
                                                    this,
                                                    android.R.layout.simple_expandable_list_item_1,
                                                    cursor,
                                                    new String[]{People.NAME},
                                                    new int[]{android.R.id.text1}
                                                    );

 

posted @ 2016-10-09 13:48  guqiangjs  阅读(176)  评论(0)    收藏  举报