基本控件
1.TextView:
功能与传统的桌面应用开发中的Label控件相似,用于显示文本信息
如:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#0000ff" android:textSize="40sp" android:text="@string/hello_world" />
显示效果:
上面的xml代码中,设置了几个常用的属性:
android:layout_width和android:layout_height分别设置控件的宽高
textColor设置显示的文本的颜色
textSize设置显示的文本的字体大小
text设置显示的文本内容。
2.Button:
前面用到的比较多,经常被用到的就是通过id获取按钮,然后绑定单击监听事件,这里仅列举个例子:
activity_main.xml:
<TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#0000ff" android:textSize="40sp" android:text="@string/hello_world" /> <Button android:id="@+id/btn" android:layout_below="@id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btnText"/>
MainActivity.java:
public class MainActivity extends ActionBarActivity { private TextView tv; private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); tv = (TextView) findViewById(R.id.tv); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub tv.setText("It's changed!"); } }); } }
3.EditText:
即文本输入框,如下修改程序,在按钮之上添加一个EditText,点击按钮,会获取EditText的值并把它设置为TextView的Text属性:
activity_main.xml:
<TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#0000ff" android:textSize="40sp" android:text="@string/hello_world" /> <EditText android:id="@+id/et" android:layout_below="@id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/hintText" /> <Button android:id="@+id/btn" android:layout_below="@id/et" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btnText"/>
MainActivity.java:
public class MainActivity extends ActionBarActivity { private TextView tv; private Button btn; private EditText et; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); tv = (TextView) findViewById(R.id.tv); et = (EditText)findViewById(R.id.et); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Editable text = et.getText(); tv.setText(text.toString()); } }); } }
运行效果:
输入值,然后点击按钮:
注意到由于EditText的layout_height属性是wrap_content,所以会随着输入内容的增多不断变大,影响整体布局。若想固定其高度,可以设置maxLines属性,设置最多只显示的行数,其他内容向上滚动
如:android:maxLines = “1”
EditText的高度就不会变化了。
4.ImageView:
使用来显示图片的一个控件,之前的程序中曾经用到过,当然,它最主要的属性肯定是要显示图片的来源了,即android:src属性,将要显示的图片存放在res/drawable中,如图片名为hero.png。要显示该图片,设置android:src=”@drawable/hero”即可。
<ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/hero"/>
显示结果:
5.ProgressBar:
即进度条,使用style属性,可以设置不同的显示风格:
1)不设置style属性或者设置为style="?android:attr/progressBarStyle" ,环形显示
2)style="?android:attr/progressBarStyleHorizontal",水平横条显示
3)style="?android:attr/progressBarStyleLarge",大号的环形显示
4)style="?android:attr/progressBarStyleSmall",小号的
进度条当然是用来显示进度的,通过findViewById()获取ProgressBar,然后使用setProgress()就可以设置当前进度,使用getProgress()可以获取当前进度。
如:
布局代码:
<ProgressBar android:id="@+id/pb" android:layout_width="match_parent" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal" android:max="100" /> <Button android:id="@+id/btn" android:layout_below="@id/pb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/add_progress"/>
Activity代码:
public class MainActivity extends ActionBarActivity { private ProgressBar pb; private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pb = (ProgressBar) findViewById(R.id.pb); btn = (Button) findViewById(R.id.btn); Log.i("PB",pb.getProgress()+""); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Log.i("PB",pb.getProgress()+""); pb.setProgress(pb.getProgress()+10); } }); } }
运行结果:
初始时,默认进度为0
多次点击按钮之后:
达到android:max所设置的最大值后,再加也不会有变化了。
6.AlertDialog:
这个控件就是弹出一个对话框,类似于桌面开发中的模态对话框,必须关闭该对话框,才能进行后续交互操作,可用于显示比较重要的内容。
AlertDialog的构造方法都是protected,没法直接通过构造来创建AlertDialog,但是可以通过其内部类Builder来创建。
具体使用可以参考帮助手册中关于这个内部类的帮助信息,下面举个简单例子:
AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle("Warning"); dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }); dialog.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }); dialog.setMessage("warning, hahaha"); dialog.show();
运行结果:
7.ProgressDialog:
类似于AlertDialog,也是对话框,不过它显示的内容是一个进度条,好像是对话框和进度条两个控件的结合。
ProgressDialog pd = new ProgressDialog(this);
pd.setTitle("Data Loading...");
pd.show();
运行结果:
自定义控件简单示例
有时候,可能觉得系统提供的控件太丑,就会需要自定义控件来实现自己想要的效果。
以下主要参考《第一行代码》
1.自定义一个标题栏:
系统自带的标题栏很丑,且没什么大的作用,所以我们之前会在onCreate()中调用requestWindowFeature(Window.FEATURE_NO_TITLE);设置不显示标题栏。
下面自定义一个标题栏,中间显示标题,左右各有一个按钮:
title.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="horizontal" android:background="#bbbbbb" > <Button android:id="@+id/btn_back" android:text="@string/back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_gravity="left|center_vertical" android:textColor="#0099cc" android:layout_weight="1"/> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:textColor="#0099cc" android:text="@string/this_is_title" android:layout_gravity="center" android:gravity="center" android:layout_weight="2"/> <Button android:id="@+id/btn_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/edit" android:layout_margin="5dp" android:layout_gravity="right|center_vertical" android:textColor="#0099cc" android:layout_weight="1"/> </LinearLayout>
Activity代码:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.title); }
运行结果:
2.复用布局代码:
想让这个标题栏应用在以后的每个布局文件,要怎么做呢?
总不能每次都把这些xml代码重写一遍吧。
android布局中提供了类似于c预处理指令#include的<include>标签,可以实现布局代码的复用。
下面新建一个first_layout.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="match_parent" android:orientation="vertical" > <include layout="@layout/title"/> <Button android:id="@+id/btn" android:text="@string/i_m_a_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"/> </LinearLayout>
修改setContentView(R.layout.first_layout);
显示结果:
现在Back和Edit按钮都没有任何事件处理的,怎样实现点击Back按钮就结束当前Activity呢?方法跟之前的做法完全一样,使用findViewById()根据id找到Back按钮,然后设置click事件监听即可。
代码如下:
public class FirstActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.first_layout); Button btn = (Button) findViewById(R.id.btn_back); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub FirstActivity.this.finish(); } }); } }
布局文件的复用已然通过<include>实现了,但是每次都要重新写事件监听,还是觉得麻烦……到这里一般就会想到抽象出一个自定义类,每次需要的时候,直接使用该自定义类不就行了,其实就是自定义控件的做法了。
3.自定义控件,复用功能代码
TitleLinearLayout.java代码:
public class TitleLinearLayout extends LinearLayout { public TitleLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.title, this); Button btn_back = (Button) findViewById(R.id.btn_back); btn_back.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Log.i("clicked","back"); ((Activity)getContext()).finish(); } }); } }
继承自LinearLayout,实现带两个参数的构造方法。在构造方法中,加载布局文件,并对其中的Back按钮进行事件监听设置。
LayoutInflater.from(context).inflate(R.layout.title, this);用于动态加载布局文件。
注意到,Activity中有一个获取LayoutInflater的方法,所以,也可以使用下面一行代码加载布局文件:
((Activity)context).getLayoutInflater().inflate(R.layout.title, this);这种方法,在Activity代码中比较常用,而这里需要进行类型强转,反倒麻烦点,而且不如第一个方法安全。
如何使用自定义的控件呢?
first_layout代码如下:
<?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="match_parent" android:orientation="vertical" > <cn.csc.custom_ui.TitleLinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> </cn.csc.custom_ui.TitleLinearLayout> <Button android:id="@+id/btn" android:text="@string/i_m_a_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"/> </LinearLayout>
说明:
1)在布局文件中,引用自定义的控件,需要使用完整的类限定名,即包名.类名的方式;
2)在定义控件中,设置属性时,使用alt+/进行代码提示补全功能将经常不可用,标签名可以先设置为内置控件,然后进行属性的设置,之后再把标签名改回到自定义的控件的完整限定名即可。
控件ListView的简单使用
MVC模式:
MVC的基本原理就是通过Controller连接View和Model。当View中所显示的数据发生变化时,会通知Controller,然后由Controller调用Model中的相关方法执行相应的数据修改操作。反之,当Model中的数据发生变化时,也会通知Controller,由Controller通知View更新显示内容。如此一来,就使得数据部分与视图部分相分离,任何一方发生改变都不会影响到另一方。
而在android中,MVC的一个常见应用就是ListView显示数据。V代表的就是显示控件;M代表的是各种数据源,可以是自己定义的List或者数组,也可以是数据库,文件等;C代表的是Adapter类,android中比较常见的adapter有:BaseAdapter,ArrayAdapter,SimpleAdapter等。
ListView通过setAdapter方法实现了其和一个Adapter对象的绑定,Adapter一般通过getView()方法返回当前列表项所要显示的View对象,完成了对Model中数据的读取。
当Model发生变化时,会调用BaseAdapter.notifyDataSetChanged()方法通知组件数据已然变化,此时Adapter就会调用getView()方法重新显示组件内容。
ListView:间接继承自抽象类AdapterView。
常见方法:
void setOnItemClickListener(AdapterView.OnItemClickListener listener)
void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener)
void setAdapter(ListAdapter adapter)
Adapter:是一个接口
主要的方法:
abstract int getCount() 返回要显示的item总数
abstract Object getItem(int position) 根据item索引返回该item
abstract long getItemId(int position) 返回item的id。
abstract View getView(int position, View convertView, ViewGroup parent)返回一个用来展示数据源中索引为position的View对象。
BaseAdapter是一个间接实现了Adapter接口的抽象类
自定义Adapter继承BaseAdapter时,需要提供上面四个方法的实现。主要要实现的是getCount()和geView()方法。
ArrayAdapter<T>, CursorAdapter, SimpleAdapter则直接继承自BaseAdapter,实现了其抽象方法。
ListView示例1:展示一个字符串数组中的各个字符串。
main_layout.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="match_parent" android:orientation="vertical" > <ListView android:id="@+id/listview" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
MainActivity.java:
public class MainActivity extends Activity { private String[] strs; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); strs = new String[]{"aaa","bbb","ccc","ddd","eee","fff","ggg","hhh","iii"}; ListView lv = (ListView) findViewById(R.id.listview); lv.setAdapter(new MyBaseAdapter()); } class MyBaseAdapter extends BaseAdapter{ @Override public int getCount() { return strs.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView tv = null; tv = new TextView(MainActivity.this); Log.i("listview", position+"get view"); tv.setText(strs[position]); tv.setTextSize(40); tv.setTextColor(Color.RED); return tv; } } }
运行结果:
注意到,每次滚动屏幕显示新的item,或将滚出屏幕上方的item重新显示出来都会调用getItem()方法。而上面的代码中每次都会新建一个TextView,这样做是存在问题的。
getView(int position, View convertView, ViewGroup parent),其中参数convertView在允许的情况下,会保存旧的View实例,以便拿来复用。所以,可以利用该参数来优化上面的getView()实现。
代码修改如下:
public View getView(int position, View convertView, ViewGroup parent) { TextView tv = null; Log.i("listview", position+"get view"); if(convertView == null){ tv = new TextView(MainActivity.this); } else{ tv = (TextView) convertView; } tv.setText(strs[position]); tv.setTextSize(40); tv.setTextColor(Color.RED); return tv; }
其实,若只是显示数组中的内容,直接使用ArrayAdapter会比较方便:
MainActivity.java修改如下:
private String[] strs; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); strs = new String[]{"aaa","bbb","ccc","ddd","eee","fff","ggg","hhh","iii"}; ListView lv = (ListView) findViewById(R.id.listview); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, strs); lv.setAdapter(adapter); }
运行结果:
其中android.R.layout.simple_list_item_1是系统自带的一个布局id。
一般来说,在ListView中显示的东西可能更加复杂点,只靠一个TextView肯定解决不了,这时,就可以为ListView中的item根据需要编写一个布局文件。
如:item_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/hero" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="35sp" /> </LinearLayout>
用于在线性布局中水平显示一个图片和一个字符串。
修改MyAdapter内部类的getView():
public View getView(int position, View convertView, ViewGroup parent) { View view = null; Log.i("listview", position+"get view"); if(convertView == null){ view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_layout, null); } else{ view = convertView; } TextView tv = (TextView) view.findViewById(R.id.tv_name); tv.setText(strs[position]); return view; }
运行结果:
另一种可能常用的Adapter是SimpleAdapter。
构造函数:SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
context指定上下文
data指定存放数据的list对象,list中存放的是Map对象。
resource指定item的布局文件id
from和to是有序的,两者中的元素必须一一对应,from中存放的是list中每个map对象中的key值,to存放的是显示对应key获取的值的控件的id。
如:item_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="35sp" /> </LinearLayout>
MainActivity.java中修改如下:
protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); ListView lv = (ListView) findViewById(R.id.listview); List<Map<String,Object>> data = new ArrayList<Map<String,Object>>(); Map<String,Object> map = new HashMap<String, Object>(); map.put("img", R.drawable.hero); map.put("str", "aaa"); data.add(map); map = new HashMap<String, Object>(); map.put("img", R.drawable.hero); map.put("str", "bbb"); data.add(map); map = new HashMap<String, Object>(); map.put("img", R.drawable.hero); map.put("str", "ccc"); data.add(map); map = new HashMap<String, Object>(); map.put("img", R.drawable.hero); map.put("str", "ddd"); data.add(map); map = new HashMap<String, Object>(); map.put("img", R.drawable.hero); map.put("str", "eee"); data.add(map); SimpleAdapter sa = new SimpleAdapter(this, data, R.layout.item_layout, new String[]{"img","str"}, new int[]{R.id.iv,R.id.tv_name}); lv.setAdapter(sa); }
显示结果:
关于ListView的事件监听:
AdapterView中定义了几个设置事件监听的方法,如:
void setOnItemClickListener(AdapterView.OnItemClickListener listener)
void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener)
ListView间接继承了AdapterView,所以,要处理事件监听时,可以调用ListView中相关的方法。
注:如果调用了ListView的setOnClickListener()方法,会报如下错误:
java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead
setOnItemClickListener()方法示例:
ListView lv = (ListView) findViewById(R.id.listview); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Log.i("listview","onClick"); Log.i("listview",view.toString()); Log.i("listview",position+""); Log.i("listview",id+""); TextView tv = (TextView) view.findViewById(R.id.tv_name); Toast.makeText(MainActivity.this, tv.getText(), Toast.LENGTH_LONG).show(); } });
运行结果:
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索button
, view
, 控件
, new
, 代码
属性
android 常用控件、android常用控件大全、android常用ui控件、android常用控件详解、android常用布局控件,以便于您获取更多的相关知识。