1、 View介绍
在Android中,所有的可视化组件都是继承自View类,用户通过View和ViewGroup或者扩展自他们的类来构建用户界面。一个View对象处理它自己的测度、布局、绘图、焦点改变、滚动、键/手势等与屏幕上矩形区域的交互。作为用户界面中的对象,View也是与用户交互的交互事件接收器。
(来自官网)
在Android中,类的继承方式如上所示,Control用来实现相对比较简单的功能,而Widget用来组合控件和构建更加复杂的控件(如用户自定义组件)。 Control也可以和widget相互转换。
2、 Layout介绍在Android应用程序中,一个视图有很多的控件,如何才能控制这些控件的位置和排列?在网页中我们可以通过Html中的table,div来布局,在Android中我们通过Layout实现布局。
在Android中主要有以下几种Layout:
- LinearLayout
LinearLayout线性布局,包含在LinearLayout里面的控件按顺序排列成一行或者一列。
主要介绍下他的两个主要的属性:
-
- Orientation——方向,当设置为Horizon时,Layout中的控件将排成一行,当设置为Vertical时,Layout中的控件将排成一行。
- FillMode——填充方式,即设置android:layout_width和android:layout_height,可以为三种值:具体的像素值、wrap_content, 表示按控件中文本实际长度显示 、 fill_parent, 表示填充剩下的所有可用空间。具体的例子可以在官网上查看,这里就不在举例了。
- RelativeLayout
RelativeLayout相对布局,它是依靠与父容器或同在一容器中其它控件的相对位置来定位的。
两种情况下的共四种主要属性:
-
- 相对父容器:
android:layout_alignParentTop: 控件的顶部与父容器的顶部对齐。
android:layout_alignParentBottom:控件的底部与父容器的底部对齐。
android:layout_alignParentLeft:控件左边与父容器的左边缘对齐。
android:layout_alignParentRight:控件右边与父容器的右边缘对齐。
-
- 相对同一容器中的其它控件:
android:layout_above: 表示此控件在另一控件的上面。
android:layout_below:表示此控件在另一个控件的下面。
android:layout_toLeftOf:表示此控件在另一个控件的左边。
android:layout_toRightOf:表示此控件在另一个控件的右边。
android:layout_alignTop: 表示此控件与另一控件顶部对齐。
android:layout_alignBottom:表示此控件与另一控件底部对齐。
android:layout_alignLeft:表示此控件与另一个控件左对齐。
android:layout_alignRight:表示此控件与另一个控件右对齐。
例子请查看官方网站的例子。
- TableLayout
表格布局,类似于HTML的Table。通过TableRow来定义一行,如果一个控件占用多列可以设置android:layout_span, 类似于HTML中Table的colspan。默认情况下一个控件是按顺序放置在每一列的(column 0, column 1….), 也可以通过android:layout_column指定放在哪一列。如果一列内容过长或者过短,可以通过android:stretchColumns和android:shrinkColumns来增加或者减少此列的宽度。
例子请查看官方网站的例子。
- AbsoluteLayout
绝对布局,就是Android不提供任何布局控制,而是由我们自己通过X坐标,Y坐标来控制组件的位置,在这个容器里面的组件位置、大小都需要我们自己来控制。
layout_x :制定该子组件的x坐标。
layout_y:制定该子组件的y坐标
非常不建议使用AbsoluteLayout来进行控件布局,因为用户手机屏幕尺寸有大有小,如果使用这个来布局,那么你想想你自己的工作量吧。
3、 Widget介绍Widget分为系统提供和用户自定义两部分,对于用户自定义部分将在后面的笔记中介绍。在Android系统中为我们提供了一个标准的View工具箱,我们只需要调用这些工具就可以创建出外观一致的应用程序。
下面是Android系统为我们提供的部分控件:
❑ TextView
标准的只读文本label。它支持多行显示、字符串格式化和文本自动换行。
❑ EditText
可编辑的文本输入框。它支持多行输入和文字换行。
❑ ListView
一个ViewGroup,以列表的方式创建和管理一组显示项。标准的ListView使用TextView来显示每一个字符串数组内的值。
❑ Spinner
组合控件,显示一个TextView和一个关联的ListView,用来从一个列表中选择一项并显示选择项在TextView中。它还有一个button,当按下时显示一个选择框。
❑ Button
标准的按钮。
❑ CheckBox
两种状态的button,代表checked或unchecked。
❑ RadioButton
单选按钮。
更多的可以查看官方帮助文档。
4、 创建一个Menu当你打开一个应用程序时,点击手机的Menu键,这个时候弹出来的那么菜单选项就是Menu。
如果要创建一个Menu菜单,需要重写onOptionsItemSelected(响应Menu选择),onCreateOptionsMenu(创建Menu菜单)这两个方法。
今天学习了View和Layout,并在结束的时候举了一个创建Menu的例子。Layout作为布局控制,对我们以后的开发及其重要,在以后的开发中必定会经常接触到。
1、在common目录下新增cmd_menu.c文件,内容为:
#include<common.h> #include<command.h> #ifdef CONFIG_MENUKEY static char awaitkey(unsigned longdelay, int* error_p) { int i; charc; if (delay ==-1) { while (1) { if (tstc()) return getc(); } } else { for (i = 0; i < delay; i++) { if (tstc()) returngetc(); udelay (10*1000); } } if(error_p) *error_p = -1; return 0; } voidmain_menu_usage(void) { printf("\r\n*****************luozhiyong*****************\r\n"); printf("\n======== User Menu ======== \n"); printf("\r\n"); printf("[1] 下载 u-boot.bin 写入 Nand Flash\r\n"); printf("[2] 下载 Linux(uImage) 内核镜像写入 Nand Flash\r\n"); printf("[3] 下载 yaffs2(fs.yaffs) 文件系统镜像写入 Nand Flash\r\n"); printf("[4] 下载 Linux(uImage) 内核镜像到内存并运行\r\n"); printf("[5]重启设备\r\n"); printf("[q] 退出菜单\r\n"); printf("\r\n"); printf("输入选择: "); } void menu_shell(void) { charc; charcmd_buf[200]; while (1) { main_menu_usage(); c = awaitkey(-1, NULL); printf("%c\n", c); switch (c) { case '1': { strcpy(cmd_buf, "tftp 0x32000000 u-boot.bin; nand erase 0x00x60000; nand write 0x32000000 0x0 0x60000"); run_command(cmd_buf, 0); break; } case '2': { strcpy(cmd_buf, "tftp 0x32000000 uImage; nand erase 0x800000x200000; nand write 0x32000000 0x80000 0x200000"); run_command(cmd_buf, 0); break; } case '3': { strcpy(cmd_buf, "tftp 0x32000000 fs.yaffs; nand erase 0x280000;nand write.yaffs2 0x32000000 0x280000 $(filesize)"); run_command(cmd_buf, 0); break; } case '4': { strcpy(cmd_buf, "tftp 0x32000000 uImage; bootm 0x32000000"); run_command(cmd_buf, 0); break; } case '5': { strcpy(cmd_buf, "reset"); run_command(cmd_buf, 0); break; } case 'q': { return; break; } } } } int do_menu (cmd_tbl_t *cmdtp, intflag, int argc, char *argv[]) { menu_shell(); return0; } U_BOOT_CMD( menu, 1, 0, do_menu, "User Menu", "U-boot Download Menu\n" ); #endif
2、修改common目录下的Makefile文件,将cmd_menu.o加入编译:
COBJS-y +=main.o COBJS-y +=cmd_menu.o COBJS-y += ACEX1K.o
至此,在终端下输入 menu 就可以看到自己创建的菜单
注:如果要开机自启动,则在main.c的#ifdef CONFIG_AUTO_COMPLETE...#endif句断后加上:
# ifdef CONFIG_MENUKEY if (menukey == CONFIG_MENUKEY) { run_command ("menu", 0); disable_ctrlc(prev); }else{ run_command (s, 0); } #endif /* CONFIG_MENUKEY */
其他相似链接:http://lanyin1225.blog.163.com/blog/static/126261290201281322430504/
下拉列表在android中自带spinner的有时候不太适合我们的界面,我们希望有自己的一种显示方法,那怎么办?自定义Spinner.效果如QQ账号选择一样。如图所以。
这种效果,如果你喜欢,你可以往下接着看。
这里我们使用listView配合TextView实现的。
1 布局文件
activity_main.xml
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="50dp" android:gravity="clip_vertical" > <LinearLayout android:id="@+id/spinnerid" android:layout_width="fill_parent" android:layout_height="50dp" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_marginTop="10dp" android:background="@drawable/preference_single_item" android:gravity="right" > <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="1234" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:textAppearance="?android:attr/textAppearanceLarge" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="match_parent" android:src="/blog_article/@drawable/mm_submenu_dropdown/index.html" /> </LinearLayout> </RelativeLayout> </LinearLayout>
myspinner_dropdown.xml这里面只有一个listView
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"> <ListView android:id="@+id/listView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@null" android:dividerHeight="1px"></ListView> </LinearLayout>myspinner_dropdown_item.xml这里就是每个item布局
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <RelativeLayout android:id="@+id/myspinner_dropdown_layout" android:layout_width="fill_parent" android:layout_height="35dp" android:background="@drawable/preference_item" android:gravity="left|center" > <TextView android:id="@+id/myspinner_dropdown_txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:text="TextView" android:textSize="20sp" /> </RelativeLayout> </LinearLayout>2程序代码实现
MyspinnerAdapter.java文件是listview的适配文件
package com.example.testspinner2; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.RelativeLayout; import android.widget.TextView; public class MyspinnerAdapter extends BaseAdapter { LayoutInflater inflater; Context context; ArrayList<String> list; public MyspinnerAdapter(Context context, ArrayList<String> list) { super(); this.context = context; this.list = list; inflater = LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return list.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = inflater.inflate(R.layout.myspinner_dropdown_items, null); viewHolder = new ViewHolder(); viewHolder.layout = (RelativeLayout) convertView.findViewById(R.id.myspinner_dropdown_layout); viewHolder.textView = (TextView) convertView.findViewById(R.id.myspinner_dropdown_txt); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } if(list.size() == position+1){ viewHolder.layout.setBackgroundResource(R.drawable.preference_last_item); }else{ viewHolder.layout.setBackgroundResource(R.drawable.preference_item); } viewHolder.textView.setText(list.get(position)); return convertView; } public class ViewHolder { RelativeLayout layout; TextView textView; } public void refresh(List<String> l) { this.list.clear(); list.addAll(l); notifyDataSetChanged(); } public void add(String str) { list.add(str); notifyDataSetChanged(); } public void add(ArrayList<String> str) { list.addAll(str); notifyDataSetChanged(); } }
这里面比较关键的是判断当前item是否为最后一个item,如果是最后一个背景需要更改,毕竟中间的背景和最后一项item是不同的
MainActivity.java
package com.example.testspinner2; import java.util.ArrayList; import android.app.Activity; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.PopupWindow.OnDismissListener; import android.widget.TextView; public class MainActivity extends Activity { private ArrayList<String> list; private ImageView imgView; private TextView textView; private LinearLayout layout; private ListView listView; private MyspinnerAdapter adapter; private PopupWindow popupWindow; private LinearLayout spinnerlayout; int width; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView2); imgView = (ImageView) findViewById(R.id.imageView1); // 实例化一个List,添加数据 list = new ArrayList<String>(); list.add("第一展厅"); list.add("4展厅"); list.add("第三展厅"); adapter = new MyspinnerAdapter(this, list); textView.setText((CharSequence) adapter.getItem(0)); spinnerlayout = (LinearLayout) findViewById(R.id.spinnerid); // 点击右侧按钮,弹出下拉框 imgView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(list.size()>0){ spinnerlayout.setBackgroundResource(R.drawable.preference_first_item); } showWindow(spinnerlayout, textView); } }); } protected void onResume(){ super.onResume(); } public void showWindow(View position, final TextView txt) { layout = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.mypinner_dropdown, null); listView = (ListView) layout.findViewById(R.id.listView); listView.setAdapter(adapter); popupWindow = new PopupWindow(position); // 设置弹框的宽度为布局文件的宽 popupWindow.setWidth(spinnerlayout.getWidth()); popupWindow.setHeight(LayoutParams.WRAP_CONTENT); // 设置一个透明的背景,不然无法实现点击弹框外,弹框消失 popupWindow.setBackgroundDrawable(new BitmapDrawable()); // 设置点击弹框外部,弹框消失 popupWindow.setOutsideTouchable(true); popupWindow.setFocusable(true); popupWindow.setContentView(layout); // 设置弹框出现的位置,在v的正下方横轴偏移textview的宽度,为了对齐~纵轴不偏移 popupWindow.showAsDropDown(position, 0, 0); popupWindow.setOnDismissListener(new OnDismissListener(){ @Override public void onDismiss() { // TODO Auto-generated method stub spinnerlayout.setBackgroundResource(R.drawable.preference_single_item); } }); // listView的item点击事件 listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub txt.setText(list.get(arg2));// 设置所选的item作为下拉框的标题 // 弹框消失 popupWindow.dismiss(); popupWindow = null; } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
这里前段和我们常用的没什么区别,只是监听imageView,关键的是showWindows做出了点击更多按钮弹出已存信息。在popupWindow消失的时候,背景变回没有弹出下拉菜单的背景样式。
可能大家没有图片资源,今天我传不上去,可以留下邮箱!