安卓成长记(二)

安卓成长记(二)

这里是介绍安卓的一些组件,也就是书上面的第二章UI界面那一章。

之前进行到FrameLayout的时候去研究Handler的消息机智了,现在回来。

不是说View是所有组件的父类么。是这样的。
textview组件(就是那个文本框)直接继承了View。而且他还是EditView和Button组件的父类。

文本中有大量的方法,查看API

EditText

他派生了两个子类,

  • AutoCompleteTextView自动完成的子类,一般和adapter搭配使用。

  • 一个是ExtractEditText:这个你一般也用不着。

下面这个xml文件是和组件的xml属性有关的:


<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="1">
    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="用户名:"
            android:textSize="16sp"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请填写登录账号"
            android:selectAllOnFocus="true"/>
            
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="numberPassword"/>
    TableRow>
    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="年龄:"
            android:textSize="16sp"/>
        
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="number"/>
    TableRow>
    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="生日:"
            android:textSize="16sp"/>
        
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="date"/>
    TableRow>
    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="电话号码:"
            android:textSize="16sp"/>
        
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请填写您的电话号码"
            android:selectAllOnFocus="true"
            android:inputType="phone"/>
    TableRow>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册"/>
TableLayout>

android:inputType这个属性很重要的。EditText输入的类型。

另外注意hint这个东西是可以改变颜色的。

可变颜色的按钮

在drawable里面可以用xml自定义Drawable对象。
他的根节点是selector。选择器?


<selector xmlns:android="http://schemas.android.com/apk/res/android">
    
    <item android:state_pressed="true"
    android:drawable="@drawable/red"
    />
    
    <item android:state_pressed="false"
    android:drawable="@drawable/purple"
    />
selector>
  • < item android:state_pressed=”false”
    android:drawable=”@drawable/purple” />

条目是选择不同的状态。

单选钮RadioButton

RadioButton是一组一组的用,搭配RadioGroup。哟一个小细节就是,如果指定了有默认选择的RadioButton,那RadioGroup之中的每一个RadioButton都要有id属性。

另外如果用了RadioGroup,加事件监听器的时候是为RadioGroup加的。

public class MainActivity extends Activity
{
    //在这里添加组件
    RadioGroup rg;
    TextView show;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取界面上rg、show两个组件
        rg = (RadioGroup) findViewById(R.id.rg);
        show = (TextView) findViewById(R.id.show);
        // 为RadioGroup组件的OnCheckedChange事件绑定事件监听器
        //下面用的是匿名对的方式。为rg绑定一个oncheckchangelistener是很常见的。
        //另外不要困惑为什么括号里面有new RadioGroup.OnCheckedChangeListener()这个
        //你把RadioGroup这个定西去掉,会报错,你import就行了,就是少引入了个包而已。
        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
        {
            @Override
            //下面这个其实一开始没有完全理解。int checkedId其实是系统传进来的,不是自己传进来的。
            public void onCheckedChanged(RadioGroup group, int checkedId)
            {
                // 根据用户勾选的单选按钮来动态改变tip字符串的值
                String tip = checkedId == R.id.male ?
                        "您的性别是男人": "您的性别是女人";
                // 修改show组件中的文本
                show.setText(tip);
                //用switch其实也行。但是注意这个是个int值。
            }
        });
    }
}

下面这个,关于imageview,你就记住
image1.setImageResource(images[++currentImg % images.length]);
setImageResource()这个函数就行了。他能接受一个int类型的id值。

下面的这一堆组件比较麻烦,就是用AdapterView的组件。
其实不是listview,spinner用adapter,而是他们本来就是AdapterView的组件,他们本来就要用到Adapter去提供内容。

这个继承图也是挺醉的:

树形啊:

viewgroup

AdapterView

AbsListView AbsSpinner AdapterViewAnimator

上面三个虽然分了一些类,但是仍然是抽象的。所以理解了为什么spinner也是需要Adapter去提供内容。

listview组件的应用:

  • 直接使用ListView

  • 让activity去继承ListActivity

ListView使用的setAdapter()方法其实是AdapterView的方法。

ListView,spinner都是容器,而Adapter负责提供列表项组件。注意是列表项

AbsListview他的这个属性很重要:

>android:choiceMode
他有几个属性值:singleChoice允许单选,multipleChoice允许多选。

我大胆的推测一下是不是LIistView列表指定了之后就能多选了?
但是那样的话返回的话是怎么返回的?

ListView本身的xml属性不多

android:divider 指定分隔条(可以直接指定颜色,可以指定Drawable资源)
android:dividerHeight 指定分隔条的高度(px像素为单位一般是)
android:entries 指定一个数组资源

利用LiseView的entries属性是很快,但是也很简陋,不能改变列表项的样式,资源也一般是固定的。
不过要是我每次读下来一个xml文件,然后显示在列表里面呢?好像也行。

重要的是entries指定的是一个数组资源。


<resources>
    <string-array name="books">
        <item>疯狂Java讲义item>
        <item>疯狂Ajax讲义item>
        <item>疯狂XML讲义item>
        <item>疯狂Android讲义item>
    string-array>
resources>

注意数组资源是在values文件夹下的,根元素是resources

如果要想为列表项弄不一样的东西,那就得动用adapter了。

Adapter本身也是一个接口,他下面有一堆子孩子,比如ListAdapter和SpinnerAdapter。他们的继承关系比较复杂,参观书上91页。

常用的是BsaseAdapter和ArrayAdapter和SimplelAdapter。

  • ArrayAdapter是一般提供数组的包装。

  • BasrAdapter用于扩展可以被扩展为任意的Adapter。

  • SimpleAdapter这个里面的参数很复杂。

-SimpleCursorAdapter通常包装cursor提供的内容。

arrayAdapter

public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ListView list1 = (ListView) findViewById(R.id.list1);
        // 定义一个数组
        String[] arr1 = { "孙悟空", "猪八戒", "牛魔王" };
        // 将数组包装为ArrayAdapter
        ArrayAdapter adapter1 = new ArrayAdapter
                (this, R.layout.array_item, arr1);
        // 为ListView设置Adapter
        list1.setAdapter(adapter1);
        ListView list2 = (ListView) findViewById(R.id.list2);
        // 定义一个数组
        String[] arr2 = { "Java", "Hibernate", "Spring" , "Android" };
        // 将数组包装为ArrayAdapter
        //我觉着吧,既然后边那个参数是一个数组,那adapter包装的应该就是一个数组,而不是丹丹的一个条目。
        //中间的参数也可以单纯的理解为是“样式”,一个条目应该有的样式。
        //数组资源我一定要写在java文件中吗?好像一般不用吧。
        ArrayAdapter adapter2 = new ArrayAdapter
                (this, R.layout.checked_item, arr2);
        // 为ListView设置Adapter
        list2.setAdapter(adapter2);
    }
}

函数的原型:

android.widget.ArrayAdapter.ArrayAdapter< String >(Context context, int resource, String[] objects)
第一个是上下文,第二个是条目的资源,第三个是数组资源。

还有一个问题。第二个参数是int resource,这个工程中的xml文件中是单独的一个Textview。
是因为这个adapter是ArrayAdapter吗?对的,这句话:
**arrayadapter虽然简单,但是只能用TextView作为列表项,功能很局限。貌似也是不能响应点击事件的。
我记得别的是可以用linearLayout的。
大概这就是为什么ArrayAdapter只适合数组的缘故吧,layout文件夹里面的条目适合用Textview去指定。

基于继承ListActivity的方法实现ListView。

基于ListAdapter的不需要实现setContentView()方法。

一般的activity都会有这个方法去显示activity_main文件,比如:

protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

他一般是在OnCreate()方法中的。

但是如果继承了ListActivity的话就不用这个方法了,直接传入一个Adapter,这样这个Activity就只剩下一个LIstView了。

public class MainActivity extends ListActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // 无须使用布局文件
        String[] arr = { "孙悟空", "猪八戒", "唐僧" };
        // 创建ArrayAdapter对象
        //连layout里面的东西也省了啊,直接用的系统的系统的界面
        //android.R.layout.simple_list_item_multiple_choice,
        //选中怎么没反应呢?应该是设置监听器。
        //这个设置监听器的比较麻烦,因为整个继承了ListActivity,里面有什么方法,什么时候调用这个方法都不知道。
        //这算是一个遗留问题:继承了activity的怎么放置监听器呢?

        ArrayAdapter adapter = new ArrayAdapter(this,
                android.R.layout.simple_list_item_multiple_choice, arr);
        // 设置该窗口显示列表
        setListAdapter(adapter);
    }
}

这个倒是省事儿啊。

SimleAdapter一个一点都simple的SimpleAdapter

SimpleAdapter有一个好长好长的构造函数:
先看下面这一堆代码:

public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 创建一个List集合,List集合的元素是Map
        //首先这个list集合就比较难理解。他是一个List集合,List可以看做是一个数组。
        //里面的元素是Map<>,而map<>是个特殊的东西,他里面的东西是靠键值对来存放的,string是key,都是字符串
        //listItems就是那个集合
        List> listItems =
                new ArrayList>();
        for (int i = 0; i < names.length; i++)
        {
            //这里是初始化liseItems这个集合,一个map相当于就是listView的一个条目。
            //map初始化的时候是HashMap。后边,因为所有的都继承了Object,所以这个后边就无所谓了。
            Map listItem = new HashMap();
            listItem.put("header", imageIds[i]);
            listItem.put("personName", names[i]);
            listItem.put("desc", descs[i]);
            listItems.add(listItem);
        }
        //这个循环做完之后,也就相当于这个List做完了,就是Adapter需要的整个的数据做完了。
        // 创建一个SimpleAdapter
        //这个函数那就有的多了:
        //android.widget.SimpleAdapter.SimpleAdapter(Context context, List>
        //data, int resource, String[] from, int[] to)
        //上下文自然不用说了,后边是那个List集合,resource是一个布局的id,你总得知道每一个条目的布局是什么样子的吧?
        //条目的样式知道了,但是哪个成分对应哪个内容呢?
        //后边俩数组就知道了: String[] from, int[] to   这俩数组就是说的哪个成分要对应在哪个组件的。
        SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems,
                R.layout.simple_item,
                new String[] { "personName", "header" , "desc"},
                new int[] { R.id.name, R.id.header , R.id.desc });
        ListView list = (ListView) findViewById(R.id.mylist);
        // 为ListView设置Adapter
        list.setAdapter(simpleAdapter);
        //于是愉快的,这个Adapter就完成了

        // 为ListView的列表项的单击事件绑定事件监听器
        list.setOnItemClickListener(new OnItemClickListener()
        {
            // 第position项被单击时激发该方法
            @Override
            //下面这些函数都是系统传过来的参数
            public void onItemClick(AdapterView parent, View view,
                                    int position, long id)
            {
                System.out.println(names[position]
                        + "被单击了");
            }
        });
        // 为ListView的列表项的选中事件绑定事件监听器
        list.setOnItemSelectedListener(new OnItemSelectedListener()
        {
            // 第position项被选中时激发该方法
            @Override
            public void onItemSelected(AdapterView parent, View view,
                                       int position, long id)
            {
                System.out.println(names[position]
                        + "被选中了");
            }
            @Override
            public void onNothingSelected(AdapterView parent)
            {
            }
        });

    }

你可能感兴趣的:(安卓成长记(二))