安卓成长记(二)

来源:互联网 发布:光翼网络班多少钱 编辑:程序博客网 时间:2024/05/16 11:25

安卓成长记(二)

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

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

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

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

EditText

他派生了两个子类,

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

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

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

<?xml version="1.0" encoding="utf-8"?><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"/>            <!--获得焦点时自动选中文本--!>    </TableRow>    <TableRow>        <TextView            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="密码:"            android:textSize="16sp"/>        <!-- android:inputType="numberPassword"表明只能接受数字密码 -->        <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"/>        <!-- inputType="number"表明是数值输入框 -->        <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"/>        <!-- inputType="date"表明是日期输入框 -->        <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"/>        <!-- inputType="phone"表明是输入电话号码的输入框 -->        <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。选择器?

<?xml version="1.0" encoding="UTF-8"?><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指定的是一个数组资源。

<?xml version="1.0" encoding="utf-8"?><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<String> adapter1 = new ArrayAdapter<String>                (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<String> adapter2 = new ArrayAdapter<String>                (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<String> adapter = new ArrayAdapter<String>(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<Map<String, Object>> listItems =                new ArrayList<Map<String, Object>>();        for (int i = 0; i < names.length; i++)        {            //这里是初始化liseItems这个集合,一个map相当于就是listView的一个条目。            //map初始化的时候是HashMap。后边,因为所有的都继承了Object,所以这个后边就无所谓了。            Map<String, Object> listItem = new HashMap<String, Object>();            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<? extends Map<String, ?>>        //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)            {            }        });    }
0 0