初识android界面布局
1.活动
活动是android开发中最基本的概念,也是最容易吸引用户的地方,是一种可以包含用户界面的组件。
Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节。具体如下:
(1)onCreat:活动第一次被创建时调用。
在onCreat方法中调用setContentView(R.layout.id)
方法可以给当前活动关联并且加载一个布局,也可以说是我们可以看得到一个界面。但是创建了一个活动必须在AndroidManifest.xml中进行注册才能够生效。 销毁一个活动可以使用activity类中的finish()方法。(ps:打开上述文件,在application标签内可以添加activity标签进行相关活动的注册。另外,主活动即点击软件图标进入的主页面,注册时需加上
(2)onStart:活动由不可见变为可见时调用。
(3)onResume:处于运行状态的活动,即准备与用户进行交互的时候调用。
(4)onPause:在系统准备去启动或恢复另一个活动的时调用。
(5)onStop:活动完全不可见时调用。
(6)onDestroy:活动即将销毁前调用。
(7)onRestart:活动由停止状态变运行时调用。
2.android布局的一些组件
-
Toast: Toast是Android系统中的一种提醒方式,在程序中使用它可以将一些提示信息通知给用户,并且一定时间之后自动消失。(ps:具体可查看相关文档, Toast.makeText(当前活动,提示内容,显示时长))
-
TextView: 用于在界面上显示文本信息。
<TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文本信息" />
-
Button: 按钮。
<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button" />
-
EditText: 文本框,允许用户输入和编辑内容。
<EditText android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="输入用户名..." />
-
ImageView: 用于在界面上展现图片的一个控件。
<ImageView android:id="@+id/imageview" android:layout_width="wrap_conten" android:layout_height="wrap_conten" android:background="#F00" android:src="@drawable/green" />
-
ProgressBar: 用于在界面上显示一个进度条。
关于进度条的进度值以及显示与隐藏可以在程序中根据具体的程序加载进度加以控制。<ProgressBar android:id="@+id/progressbar" android:layout_width="wrap_conten" android:layout_height="wrap_conten" />
-
AlertDialog: 在当前界面弹出一个对话框,具体参数有
setTitle()设置对话框标题
setMessage()设置对话框内容
setCancelable()设置对话框是否为可关闭
setPositiveButton()设置确认按钮
setNegativeButton()设置取消按钮 -
ProgressDialog: 在当前界面弹出一个带有进度条的弹框,具体用法与AlertDialog类似。
3.Intent实现页面的跳转
- 显式intent使用 在按钮的点击事件中设置,首先构建一个Intent对象 Intent intent = new Intent(当前活动,目标活动),其次调用方法startActivity(intent)方法即可启动目标活动。到此,则可以实现点击改按钮跳转到另外一个页面简单切换了。
- 隐式intent使用 通过在活动注册时候的
标签内为活动配置相应的自定义category,通过在intent对象中调用addCategory(category)为intent配置响应页面的category可实现对应页面的跳转。(intent中还可以设置android中的内置动作,比如拨号,网页跳转等等,具体可以参考《第二行代码》)
4.四种基本布局
-
线性布局
LinearLayout:垂直排列 or 水平排列 android:orientation 属性可以指定控件的排列方向 android:orientation = "vertical" 垂直排列 android:orientation = "horizontal"水平排列 android:layout_gravity 可以指定控件在布局中的对齐方式, 具体值有top,center_vertical,bottom等等, 但有一点需要注意的是,当布局排列方向为水平的时候, 只有垂直方向上的对齐方式才会生效,反之亦然。 另外LinearLayout中还有一个重要属性 android:layout_weight这个属性代表该控件所占有的权值, android:layout_weight的真实含义是: 一旦View设置了该属性(假设有效的情况下), 那么该 View的宽度等于原有宽度 (android:layout_width)加上剩余空间的占比!
-
相对布局
RelativeLayout:通过相对定位的方式让控件出现在布局的任何位置。 相对于父布局的定位: android:layout_alignParentLeft = "true" android:layout_alignParentRight = "true" android:layout_alignParentTop = "true" android:layout_alignParentBottom ="true" android:layout_centerInParent = "true" 这几个属性从名字就可以看出来,分别实现与父布局左,右,上,下对齐 以及居中显示的作用,可以同时指定两个属性实现左上,右下等等的对齐方式。 相对于控件的定位: android:layout_above = "@id/button" android:layout_below = "@id/button" android:layout_toRightOf = "@id/button" android:layout_toLeftOf = "@id/button" 分别实现定位到指定控件的上下右左方向。
-
帧布局
FrameLayout:没有方便的定位方式,但是所有的控件都会默认摆放在布局的左上角。 可以通过layout_gravity属性指定定位方式。 相对于其他布局,FrameLayout的应用场景较少。
-
百分比布局
可以直接指定控件在布局中所占的百分比决定控件的大小,可以不使用wrap_content,matchparent来指定控件大小。 百分比只为帧布局和相对布局进行功能扩展,原有的特性还在。因为线性布局本身已经支持按比例指定控件大小了(layout_weght)。 使用百分比布局需在app/build.gradle的dependencies闭包中添加: compile 'com.android.support:percent:24.2.1' PercentFrameLayout:百分比帧布局 PercentRelativeLayout:百分比相对布局 通过在控件中添加: app:layout_widthPercent ="50%" app:layout_heightPercent ="50%" 指定控件所占布局的百分比。
5.ListView
-
用来展示列表,可以向上向下的滑动,类似于刷微博,QQ聊天等。
-
ListView显示数据需要使用适配器(adapter)将数据映射到ListView上。
-
数据,包括具体将被映射的字符串,图片或者基本组件。
-
ListView与ListView布局以及数据关联:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(当前activity类.this,android.R.layout.listview子项布局xml,data) <-String为data数据类型,也可以是自己定义的数据类,但是自定义数据类的同时需要自定义适配器类,可以继承自ArrayAdapter,也可以是其他适配器类型-> ListView listview = (ListView) findViewById(R.id.list_view) listview.setAdapter(adapter) <-将构建好的适配器对象传给listview->
-
自定义适配器类型
数据类 public class Fruit { private String name;//水果名字 private int imageId;//水果图片id public Fruit(String name,int inmageId){ this.name=name; this.imageId=imageId; } public String getName(){ return name; } public int getImageId(){ return imageId; } } 适配器类 public class FruitAdapter extends ArrayAdapter<Fruit>{ private int resourceId; public FruitAdapter(Context context,int textViewResourceId,List<Fruit> object){ super(context,textViewResourceId,object); resourceId=textViewResourceId; } @Override public View getView(int position,View convertView,ViewGroup parent){ Fruit fruit =getItem(position);//获取当前项的Fruit实例 View view =LayoutInflater.from(getContext()).inflate(resourceId,parent,false);//为获取的子项加载传入的布局 ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView)view.findViewById(R.id.fruit_name); fruitName.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view;//返回布局 } } //需重写父类的构造函数,以及getView()方法,该方法在每个子项被滚动到屏幕内的时候被调用; 存在问题1:getView()方法每次都将布局重新加载一遍,当ListView快速滑动时将成为性能的瓶颈。 改进1:getView()方法中还有一个convertView参数,会自动为之前加载好的布局进行缓存。 利用该特性,在getView()加入以下代码 if(convertView == null){ view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false); }else { view = convertView; } //判断若之前从未加载过布局,则利用layoutinflater加载,否则直接从缓存convertView中读取即可。 存在问题2:getView()方法中每次都需要重复获取控件实例。 改进2:同样利用缓存的思想实现并且借助ViewHolder内部类对控件进行缓存。 如下先实现一个内部类ViewHolder: class ViewHolder{ ImageView fruitImage; TextView fruitName; } getView(){ …… ViewHolder viewHolder; if(convertView == null){ view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false); viewHolder = new ViewHolder(); viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image); viewHolder.fruitName = (TextView)view.findViewById(R.id.fruit_name); view.setTag(viewHolder);//将viewHolder存储在View中 }else { view = convertView; viewHolder = (ViewHolder)view.getTag;//重新获取ViewHolder } }
ListView的点击事件设置
在activity类中注册监听器实现点击事件
listView.setOnItemClickListener(new AdapterView.onClickListener()){
@Override
public void onItemClick(AdapterView<?> parent,View view,int position,long id){
Fruit fruit = fruitList.get(position);
Toast.makeText(MainACtivity.this,fruit.getName(),Toast.LENGTH_SHORT).show();
}
}
//当用户点击ListView中的任何一个子项时,都会调用onItemClick方法,通过position参数判断用户点击的是哪一个子项,从list中获取相应的数据,通过toast显示出来。
6.RecyclerView---更加强大的滚动控件
属于新增控件
需要添加如下依赖:
compile 'com.android.support:recyclerview-v7:24.2.1'
RecyclerView的适配器
新建适配器类继承自RecyclerView.Adapter,内部同样实现一个内部类ViewHolder继承自新建适配器类继承自RecyclerView.ViewHolder,用来实现对控件的缓存。并且实现适配器的构造方法,并重写onCreatViewHolder,onBindViewHolder,getItemCount等方法。
-
onCreatViewHolder(),用于加载布局并且创建ViewHolder实例,返回一个ViewHolder实例。
-
onBindViewHolder(),当每个子项被滚动到屏幕内的时候调用,对RecyclerView子项进行赋值
-
getItemCount(),返回RecyclerView的子项个数,返回list的长度即可。
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayout(layoutManager); FruitAdapter adapter = new FruitAdapter(fruitlist); recyclerView.setAdapter(adapter); //layoutManager用于指定RecyclerView的布局方式,LinearLayoutManager是线性布局的 意思。
-
相比于ListView,RecyclerView还可以实现横向滚动,网格布局和瀑布流布局,具体可以参考
-
关于RecyclerView的点击事件,ListView实现对子项布局中某个控件的点击事件可能比较复杂,但是RecyclerView可以很轻松的实现整个子项布局的点击或者自相布局中某个控件的点击事件。具体可参考《第二行代码》。