Android应用大部分UI组件都放在android.widget包及其子包、android.view包及其子包中,所有UI组件都继承了View类,Android采用“组合器”设计模式来设计View和ViewGroup(ViewGroup是View的子类),Android图形用户界面的组件层次如下图:

Android开发实践 界面编程(上)_第1张图片

在此强烈建议阅读官方文档(Documentation for Android SDK,打开index.html,Develop -> API Guides / Reference)。


Android中布局建议采用XML布局文件和Java代码(变化多、行为控制复杂的用Java代码)混合控制UI界面

下面我们开始Android界面编程的大探险(一些简单的属性,例如layout_width、layout_height等,下面将不再赘述)。



1.UI控件-布局管理器


所有布局管理器都是ViewGroup的子类,Android布局管理器类图(StarUML绘制)如下:

Android开发实践 界面编程(上)_第2张图片

1)线性布局LinearLayout

<span style="font-size:14px;">android:orientation=""设置布局管理器内组件的排列方式,horizontal水平、vertical垂直(默认)android:gravity=""用于控制它所包含的子元素的对齐方式android:layout_gravity=""设置该子元素在父容器中的对齐方式</span>

2)表格布局TableLayout

通过添加TableRow、其他组件控制表格行数、列数
<TableRow>..</TableRow>添加1个表格行android:shrinkColumns="1"指定第2列允许收缩android:stretchColumns="2"指定第3列可以被拉伸android:stretchColumns="1,2"指定第2、3列可以被拉伸android:collapseColumns="1"指定第2列被隐藏

3)帧布局FrameLayout

android:layout_gravity=""

4)相对布局RelativeLayout

android:gravity=""android:ignoreGravity=""设置哪个组件不受gravity影响android:layout_centerHorizontal=""定义该组件位于父容器水平居中android:layout_centerInParent=""定义该组件位于父容器中间android:layout_above="@id/abc"定义该组件位于abc组件的上方android:layout_below="@id/abc"定义该组件位于abc组件的下方android:layout_toLeftOf="@id/abc"定义该组件位于abc组件的左边android:layout_alignLeft="@id/abc"控制该组件位于abc的左边界对齐android:layout_alignParentLeft="@id/abc"  控制该组件是否与布局容器左边对齐

5)网格布局GridLayout

GridLayout是Android4.0新增的布局管理器

<span style="font-size:14px;">android:alignmentMode=""设置GridLayout采用的对齐模式android:columnCount="4"设置网格列数量android:columnOrderPreserved=""设置网格容器是否保留列序号android:rowCount=""设置网格行数量android:rowOrderPreserved=""设置网格容器是否保留行序号android:useDefaultMargins=""设置GridLayout是否使用默认的页边距</span>

6)绝对布局AbsoluteLayout

(已过时,这里不再探讨。)


2.UI组件-TextView及其子类


TextView及其子类类图如下:

Android开发实践 界面编程(上)_第3张图片

TextView和EditText最大区别在于TextView不允许用户编辑文本内容。

1)TextView属性

android:drawableEnd="@drawable/icon"设置文本框结尾处绘制图片android:ellipsize="middle"设置中间省略 android:textAllCaps="true"设置所有字母大写android:autoLink="email|phone"对邮件、电话增加链接android:shadowColor="#0000ff"设置文字阴影android:shadowDx="10.0"android:shadowDy="8.0"android:shadowRadius="3.0"android:password="true"设置密码框

2)CheckedTextView属性

<CheckedTextViewandroid:layout_width="match_parent" android:layout_height="wrap_content"android:text="可勾选的文本"android:checkMark="@drawable/ok" />通过checkMark设置该文本框的勾选图标

3)圆角边框、渐变背景的TextView

main.xml<?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" ><TextViewandroid:layout_width="match_parent" android:layout_height="wrap_content"android:text="带边框的文本"android:background="@drawable/bg_border" /><TextView  android:layout_width="match_parent"android:layout_height="wrap_content"android:text="圆角边框、渐变背景的文本"android:background="@drawable/bg_border2" /></LinearLayout>bg_border.xml<?xml version="1.0" encoding="UTF-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="#0000"/> <!-- 设置背景色为透明色 --><stroke android:width="4px" android:color="#f00" /><!-- 设置红色边框 --></shape>bg_border2.xml<?xml version="1.0" encoding="UTF-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"    android:shape="rectangle">    <!-- 指定圆角矩形的4个圆角的半径 -->   <corners android:topLeftRadius="20px"android:topRightRadius="5px"android:bottomRightRadius="20px"android:bottomLeftRadius="5px"/><!-- 指定边框线条的宽度和颜色 --><stroke android:width="4px" android:color="#f0f" /> <!-- 指定使用渐变背景色,使用sweep类型的渐变,颜色从红色→绿色→蓝色 --><gradient android:startColor="#f00"    android:centerColor="#0f0"    android:endColor="#00f"    android:type="sweep"/></shape>

4)EditText组件的用法

<!-- android:selectAllOnFocus="true" 若文本框内容可选择,设置当它获取焦点时自动选中所有文本 --><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:hint="请填写登录帐号"android:selectAllOnFocus="true" /><!-- inputType="numberPassword" 表明只能接收数字密码  inputType="number"表明是数值输入框  inputType="date"表明是日期输入框  inputType="phone"表明是输入电话号码的输入框 --><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="numberPassword" />

5)Button组件的用法

<!-- 文字带阴影的按钮 --><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="文字带阴影的按钮"android:shadowColor="#aa5"android:shadowRadius="1"android:shadowDx="5"android:shadowDy="5" /><!-- 普通文字按钮 --><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/red"android:text="普通按钮" /><!-- 带文字的图片按钮--><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/button_selector"android:text="带文字的图片按钮" /><!-- 意图过滤器 -->button_selector.xml<?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>

6)点9图片

实现只缩放图片中的某个部分的效果(可用于屏幕适配)
draw9patch工具 --> sdk\tools\draw9patch.bat

Android开发实践 界面编程(上)_第4张图片

7)单选按钮(RadioButton)与复选框(CheckBox)的用法

RadioButton与CheckBox的不同在于一组RadioButton只能选中其中一个,因此RadioButton常与RadioGroup一起使用,用于定义一组单选按钮。如下定义了一个让用户选择的输入界面:

main.xml

<?xml version="1.0" encoding="utf-8"?><TableLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><TableRow><!-- 定义一组单选框 --><RadioGroup android:id="@+id/rg"android:orientation="horizontal"android:layout_gravity="center_horizontal"><!-- 定义两个单选框 --><RadioButton android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/javaee"android:text="JavaEE"android:checked="true" /><RadioButton android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/android"android:text="Android" /></RadioGroup></TableRow><TableRow><!-- 定义一个垂直的线性布局 --><LinearLayout android:layout_gravity="center_horizontal"android:orientation="vertical"android:layout_width="wrap_content"android:layout_height="wrap_content"><!-- 定义三个复选框 --><CheckBox android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="A"android:checked="true" /><CheckBox android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="B" /><CheckBox android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="C" /></LinearLayout></TableRow><TextView android:id="@+id/show"android:layout_width="wrap_content"android:layout_height="wrap_content"/></TableLayout>
CheckButtonTest.java

下面添加事件监听采用了“委托式”事件处理机制(当事件源上发生事件时,该事件会激发该事件源上的监听器的特定方法)。

public class CheckButtonTest extends Activity {private RadioGroup rg;private TextView show;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);rg = (RadioGroup) findViewById(R.id.rg);show = (TextView) findViewById(R.id.show);// 为RadioGroup组件的OnCheck事件绑定事件监听器rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {// 根据用户勾选的单选按钮来动态改变tip字符串的值String tip = checkedId == R.id.javaee ? "您最热爱的技术是JavaEE": "您最热爱的技术是Android";// 修改show组件中的文本。show.setText(tip);}});}}

8)其他

状态开关按钮(ToggleButton)

开关(Switch)

时钟(AnalogClock和DigitalClock)

计时器(Chronometer)

详细使用方法请查阅Android官方文档,这里不再赘述。

3.UI组件-ImageView及其子类


ImageView及其子类类图如下:

Android开发实践 界面编程(上)_第5张图片

ImageView继承View组件,任何Drawable对象都可以使用ImageView来显示。

1)图片浏览器 - 实现增大降低透明度、下一张功能

main.xml

<?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"><LinearLayoutandroid:orientation="horizontal" android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"><Button android:id="@+id/maxus"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="增大透明度" /><Button android:id="@+id/minus"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="降低透明度" /><Button android:id="@+id/next"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下一张" /></LinearLayout><!-- 定义显示图片整体的ImageView --><ImageView android:id="@+id/image1"android:layout_width="match_parent"android:layout_height="240px"android:src="@drawable/image1"android:scaleType="fitCenter"/><!-- 定义显示图片局部细节的ImageView --><ImageView android:id="@+id/image2" android:layout_width="120dp"android:layout_height="120dp"android:background="#00f"android:layout_marginTop="10dp"/></LinearLayout>
ImageViewTest.java
public class ImageViewTest extends Activity {// 一个访问图片的数组int[] images = new int[]{R.drawable.image1,R.drawable.image2,R.drawable.image3,R.drawable.image4,R.drawable.image5,};// 默认显示的图片int currentImg = 2;// 图片的初始透明度private int alpha = 255;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);final Button maxus = (Button) findViewById(R.id.maxus);final Button minus = (Button) findViewById(R.id.minus);final ImageView image1 = (ImageView) findViewById(R.id.image1);final ImageView image2 = (ImageView) findViewById(R.id.image2);final Button next = (Button) findViewById(R.id.next);// 查看下一张图片的监听器next.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 设置ImageView显示下一张图片image1.setImageResource(images[++currentImg % images.length]);}});// 改变图片透明度的方法OnClickListener listener = new OnClickListener() {@Overridepublic void onClick(View v) {if (v == maxus) {alpha += 20;}if (v == minus) {alpha -= 20;}if (alpha >= 255) {alpha = 255;}if (alpha <= 0) {alpha = 0;}// 改变图片的透明度image1.setAlpha(alpha);}};// 为两个按钮添加监听器maxus.setOnClickListener(listener);minus.setOnClickListener(listener);image1.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View view, MotionEvent event) {BitmapDrawable bitmapDrawable = (BitmapDrawable) image1.getDrawable();// 获取第一个图片显示框中的位图Bitmap bitmap = bitmapDrawable.getBitmap();// bitmap图片实际大小与第一个ImageView的缩放比例double scale = bitmap.getWidth() / 320.0;// 获取需要显示的图片的开始点int x = (int) (event.getX() * scale);int y = (int) (event.getY() * scale);if (x + 120 > bitmap.getWidth()) {x = bitmap.getWidth() - 120;}if (y + 120 > bitmap.getHeight()) {y = bitmap.getHeight() - 120;}// 显示图片的指定区域image2.setImageBitmap(Bitmap.createBitmap(bitmap, x, y, 120, 120));image2.setAlpha(alpha);return false;}});}}



4.UI组件-AdapterView及其子类(一)


AdapterView继承了ViewGroup,它的本质是容器。AdapterView显示的多个列表项由Adapter提供,调用AdapterView的setAdapter(Adapter)方法设置Adapter即可。

AdapterView派生了三个子类:AbsListView、AbsSpinner、AdapterViewAnimator,这三个子类也是抽象的,实际使用往往采用它们的子类。AdapterView及其子类类图如下:

Android开发实践 界面编程(上)_第6张图片

Adapter及其子类类图如下:

Android开发实践 界面编程(上)_第7张图片

1)基于数组的ListView

\res\layout\main.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent" ><!-- 直接使用数组资源给出列表项  设置使用红色的分隔条 --><ListView  android:layout_width="fill_parent" android:layout_height="wrap_content" android:entries="@array/dev"android:divider="#f00"android:dividerHeight="2px"android:headerDividersEnabled="false" /></LinearLayout>\res\values\arrays.xml<?xml version="1.0" encoding="UTF-8"?><resources><string-array name="dev"><item>Java</item><item>JavaEE</item><item>Android</item></string-array></resources>

2)使用ArrayAdapter创建ListView

布局文件如下:

\res\layout\main.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><!-- divider="#f00" 设置使用红色的分隔条 --><ListView  android:id="@+id/list"android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#f00"android:dividerHeight="2px"android:headerDividersEnabled="false" /></LinearLayout>\res\layout\array_item.xml<?xml version="1.0" encoding="utf-8"?><TextViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/TextView"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="24dp"android:padding="10px"android:shadowColor="#f0f"android:shadowDx="4"android:shadowDy="4"android:shadowRadius="2"/>

ArrayAdapterTest.java

public class ArrayAdapterTest extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);ListView list = (ListView) findViewById(R.id.list);String[] arr = { "Java", "JavaEE", "Android" };// 创建ArrayAdapter对象ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.array_item, arr);// 设置Adapterlist.setAdapter(adapter);}}
另外,基于ListActivity实现列表,只需要去除ListView布局文件,然后修改ArrayAdapterTest.java如下:
public class ArrayAdapterTest extends ListActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//无须使用布局文件String[] arr = { "Java", "JavaEE", "Android" };// 创建ArrayAdapter对象ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, arr);// 设置AdaptersetListAdapter(adapter);}}

3)继承BaseAdapter实现ListView

继承BaseAdapter可取得对Adapter最大的控制权。下面我们简单实现一下, 布局文件如下:

main.xml

<?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" ><ListViewandroid:id="@+id/myList"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>
adapter_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="55dp"        android:layout_marginLeft="5dp"        android:gravity="center_vertical"        android:orientation="vertical" >        <TextView            android:id="@+id/tv_name"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:singleLine="true"            android:text="哈哈哈"            android:textSize="16sp" />    </LinearLayout></LinearLayout>
下面来看看具体代码实现,首先设置全局变量和编写实体类
/** * 设置全局变量 * 注意:需要在AndroidManifest.xml中做配置 */public class MyApplication extends Application{private static Context context;//全局的上下文//app的入口函数@Overridepublic void onCreate() {super.onCreate();//初始化COntextcontext = this;}/** * 获取全局的上下文 * @return */public static Context getContext(){return context;}}
/** * 实体类 */public class AppInfo {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}

然后再来看看BaseAdapterTest.java

public class BaseAdapterTest extends Activity {private ArrayList<AppInfo> list ;private ListView myList;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);myList = (ListView) findViewById(R.id.myList);... // 解析json或者xml,获取请求的数据myList.setAdapter(new MyAdapter(list));}}
MyAdapter.java(已做优化处理)
public class MyAdapter extends BaseAdapter {private ArrayList<AppInfo> list;public MyAdapter(ArrayList<AppInfo> list) {super();this.list = list;}/** * 设置条目个数 */@Overridepublic int getCount() {return list.size();}/** * 获取对应条目的数据 */@Overridepublic Object getItem(int position) {return null;}/** * 获取对应条目的id */@Overridepublic long getItemId(int position) {return 0;}/** * 设置条目样式 */@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if(convertView==null){convertView = View.inflate(MyApplication.getContext(), R.layout.adapter_main, null);}ViewHolder holder = ViewHolder.getHolder(convertView);// 获取实体类<AppInfo>,设置数据AppInfo appInfo = list.get(position);holder.tv_name.setText(appInfo.getName());return convertView;}/** * 利用ViewHolder进行性能优化 */static class ViewHolder{TextView tv_name;public ViewHolder(View convertView){tv_name = (TextView) convertView.findViewById(R.id.tv_name);}public static ViewHolder getHolder(View convertView){ViewHolder holder = (ViewHolder) convertView.getTag();if(holder==null){holder = new ViewHolder(convertView);convertView.setTag(holder);}return holder;}}}


更多相关文章

  1. 1.3 Android App 组件架构
  2. 通过xml布局文件实现按钮改变焦点设置背景图片
  3. Android 获取手机上图片和视频的缩略图 Android thumbnails .
  4. Android架构组件(二)——LiveData
  5. Android ListView滑动过程中图片显示重复错位闪烁问题解决
  6. flutter包名,应用名称,图标,启动图片修改
  7. Android TextView加载html图片详解
  8. android 调用图库中选择的图片
  9. android 图片溢出问题2...[geoway]

随机推荐

  1. Android,iOS打开手机QQ与指定用户聊天界面
  2. Android建立模拟器进行调试
  3. android String 特殊字符处理
  4. Android与H5交互——设置本地缓存
  5. Android 导入android源码有错,R.java文件
  6. Android使用DrawerLayout实现抽屉式侧滑
  7. Android(安卓)SdCard 新建文件夹并在文件
  8. 报错: Caused by: java.lang.RuntimeExce
  9. android的系统权限定义
  10. Android SearchView