五大布局:
【常用】LinearLayout 线性布局 RelativeLayout 相对布局
【不常用】FrameLayout 帧布局 AbsoluteLayout 绝对布局 TableLayout 表格布局
如果控件属性中设置了layout_weight,那么该控件的layout_width=0才可以使得layout_weight有效,即按照layout_weight\weightSum(LinerLayout的属性)的比例来进行长度设置,否则按照layout_with来确定长度。
如果没有weightSum,则控件长度按照控件各自的layout_weight来进行比例划分、
线性布局LinerLayout的特点:1、要么横向、要么纵向 2、可以根据weight来按照比例设置控件长度
相对布局RelativeLayout的特点:
1、基于父布局的上下左右【layout_alignParentRight="true"】
2、基于另外一个控件的上下左右【layout_toLeftOf="@+id/button"】【layout_above="@+id/button"】
3、和另一个控件上下左右边对齐【layout_alignTop="@+id/button"】
通过margin【外边距】进行布局:layout_marginLeft = "100dp"
相对的,padding是指内边距,即控件中的内容相对于控件左边缘的距离
FrameLayout属于将加入的控件一层层堆砌起来,几乎不使用。
AbsoluteLayout将控件以坐标形式将控件在屏幕中的方位绝对固定下来,但是考虑到安卓的屏幕各种各样,大小各不同,所以不推荐使用、
TableLayout 在layout中放置TableRow,一个TableRow即为表格的一行,在TableRow中放置控件就整理排列成为表格的一行,下一个TableRow即为下一个一行,该布局用于布局特定的表格布局。
减少布局层次的重要性
层次越多系统加载该APP需要的资源和时间就越多【就越卡甚至闪退】
官方建议布局层次:最多10层【由于我们的布局本身外面就已经包了几个层次,如FrameLayout所以实际上布局层次小于10层】
如何减少:学会使用相对布局
有些效果可以由控件和控件组合产生 如何组合
一些有用的属性:布局如何引用相同的部分
<include/>重用布局文件
将layout引用到现在的视图中
<merge/>减少视图层级
有时我们的视图外面包装一层用不上的layout【如LinearLayout】,将其以merge标签替代其他属性不变,这样操作不会改变原本的视图效果,更重要的是,在使用include来重用布局文件时,自动忽略被merge标签替换的“无用的”layout,如此起到减少布局层次的问题。
<ViewStub/>
打开页面进行预加载,但不加载完全,等到需要时才加载,如此优化视图、
总结:如何优化布局
1、减少层次
2、减少无用布局
3、布局结构要清晰
4、选择合适的布局
ps:不要嵌套多个使用layout_weight属性的LinearLayout【会大大影响APP性能】
Android lint : 帮助删除没有使用的控件、代码等
HierarchyViewer:帮助分析所有的层级
无比重要的ListView
1.1.ListView常用属性详解
android:listSelector="@android:color/transparent"
item被点击时的背景颜色
android:scrollingCache="false"
android:cacheColorHint="#00000000"
滚动缓存
首先要为ListView调用setAdapter()方法为其设置Adapter【适配器】,Adapter完成了视图与数据之间的绑定【电话簿里面的联系人信息就是在Adapter中设置的】,Adapter 需要提前新建,其内部有四个方法:
getCount()【返回数据总数】
getItem()【返回数据对象】
getItemId()【返回对象的序号】
getView()【返回一个视图】【getView是我们需要在其内部做文章的】
新建Adapter时需要设置一个构造器,将Context传进去【由构造器进行初始化】
使用LayoutInflater对布局进行解析
构造器代码如下:
private Context mContext;
private LayoutInflater mLayoutInflater;
public PhoneBookAdapter (Context context){
mContext= context;
mLayoutInflater= (LayoutInflater)= mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
getView方法代码如下:
public View getView(int position,View convertView,ViewGroup parent) {
convertView =mLayoutInflater.inflate(R.layout.item_phone_book_friend,null);
//对item布局进行解析,并将解析后的布局赋给convertView将每个联系人(item)的xml视图转为converView并且读出来,如此可以对item的视图进行操作、
TextView nameTextView = (TextView) convertView.findViewById(R.id.name_text_view);
nameTextView.setText(mNames[position]);
return convertView;
//返回一个视图
}
首先要有一个ListView,它是一个容器、一个箱子,假如ListView是一个大房子,那么房子里面有几个大柜子排列在一起i,一个柜子是一个item视图,柜子里面有一格格的数据,我们要把数据塞到柜子里面,柜子会自动分配格子。
房子里面有柜子,柜子里面有数据。如此完成了匹配
也可以选择单独创建一个类,如private List mUserInfos=new ArrayList<>();
如此需要list的activity中即ListViewDemoActivity中新建Adapter时,将userInfos传入进去
代码如下
PhoneBookAdapter phoneBookAdapter =new PhoneBookAdapter(ListViewDemoActivity.this,userInfos);
mPhoneBookListView.setAdapter(phoneBookAdapter);
setText()需要传入一个字符串,如果传入一个int型变量,则setText()会认为int变量为在资源ID,导致找不到对应资源,程序崩溃。这时需要对其进行一个转换
ageTextView.setText(mUserInfos.get(position).getmAge()); 转换前
ageTextView.setText(String.valueOf(mUserInfos.get(position).getmAge()); 转换后
ps:还可以在其后面加上一个“ ”,相当于字符串拼接,这样会将int转换为String
ListView的使用流程:
1、要有一个Activity,Activity引用了一个界面,界面中有一个ListView控件,在Activity中创建列表数据,列表内部可以有任意数据,接着构建桥梁Adapter,Adaptr中的几个重要方法:构造器【可以供我们初始化数据】,getView中使用LayoutInflater的inflate方法将item的xml解析出来【创建item的xml文件】,然后引用每个控件,进行数据绑定,最后return convertView
点击和长按事件:
在Activity中为ListView设置setOnItemClickListener【点击事件】 不需要返回值
在Activity中为ListView设置setOnItemLongClickListener【长按事件】需要返回值,即return false/
ListView中更新数据需要使用Adapter调用notifyDataSetChanged,使用该方法的话需要将Adapter变为final【AS会自动添加】或者使其成为全局变量
新建另外一批数据
替换掉老的数据
刷新listview,使其更新自己的视图
mUserInfos.clear(); mUserInfos.add(newUserInfo("我是新的数据A",1024));
public voidrefreshData(List userInfos){
mUserInfos= userInfos;
notifyDataSetChanged();
如何提高性能:
在getView中设置一个条件if (convertView == null)
{ convertView =mLayoutInflater.inflate(R.layout.item_phone_book_friend,null); }
如此可以有效减少convertView的加载次数,实现converView的复用、
缓存加载过的控件:
首先定义一个ViewHolder
listSelector 被点击时背景颜色改变
scrollingCache 滑动时缓存的颜色
cacheColorHint 缓存的颜色值
fastScrollEnable 是否允许快速滚动
常用方法:addHeaderView 【微信朋友圈,朋友圈上面是自己的空间背景和头像】 addFooterView
android:visibility="gone" 【该控件完全消失】【完全消失】
android:visibility="invisible"【该控件看不到但是依然占用空间】【穿上隐身斗篷】
选中一段代码,邮件-refactor-extract-method 可以将其抽象成为一个方法
监听器的设置:
可以导入View的OnClickListener接口,然后在设置监听器的时候不需要再new出一个,只需要传入this就可以,然后在public void onClick(View v)方法中使用switch来处理各个组件id被点击以后的逻辑。
代码如下:
public class MainActivity extends AppCompatActivity implementsView.OnClickListener{}
findViewById(R.id.button01).setOnClickListener(this);
@Override
public void onClick(View v) {
switch(v.getId()){
caseR.id.button01:
Intent intent =newIntent(MainActivity.this,ListViewDemoActivity.class);
startActivity(intent);
break;
caseR.id.button02:
break;
}
}
GridView与ListView最大的不同在于一个属性:numColumns
numColumns = 2 :联系人排成两列
numColumns = auto_fit【系统自适应】
如果不设置numColumns,其默认为1,效果与ListView一样
其他重要属性:columnWidth 每一列的宽度 horizontalSpacing 水平方向每一列的空间
verticalSpacing 垂直方向每一列的空间
微信上哪些地方使用了GridView
微信发送消息栏的加号选择
微信表情选择
相册的选择
微信的朋友圈显示
头像
ScrollView实现了不是列表的内容区的滚动方法
只支持垂直滚动
ScrollView内部只能有一个child【一般在里面方LineraLayout】
HorizontalScrollView支持水平滚动
快捷键整理:
Command + / 注释与反注释代码
ps:option+enter【新建布局文件】
command+n【新建文件】
alt + enter 【导入包】
ctrl + alt + F 【插入全局变量】
shift + F6 【重构变量rename,该变量相关的地方全部改变】
command + - 使@string/phone_book 显示为实际的字符串 "电话本"
开发心得:纸上得来终觉浅,绝知此事要躬行,看视频的时候觉得各个控件的属性简单易学稀松平常,自信心爆炸,真让自己动手模仿微信的”关于“界面做出一个相似的界面的时候还是被难倒了,明明那么简单的一个界面真正自己写的时候却问题频出:
1、ListView与父控件的左右有空隙,虽然listview的layout_width设置为match_parent但是空隙依然无法消除,这个时候需要将RelativeLayout中的android:paddingLeft和android:paddingRight设置为0
2、在layout文件中引用drawable资源的时候代码没有出错,但是系统总数莫名其妙的崩溃,那个时候需要检查自己引用的drawable资源,看其内存大小,一般内存在xK~xxK之间drawable资源才可以被引用而且被系统解析,如果像我今天一样失误引用的那个微信图标大小在1.8M左右,引用该资源代码不会报错,但是在解析使用该资源的时候,系统会崩溃。所以我的解决方法是在网上重新下载了微信图标17K左右,将原来的图标删掉,替换新图标再重新引用,问题迎刃而解。
最后,感谢极客班的各位同学的帮助,第一周的手残卸载掉haxm使得AndroidStudio模拟器无法启动,第二周的因为引用drawable资源内存太大导致系统莫名其妙的崩溃以及padding问题,都是群里面的各位热心大神帮助解答的,感谢大家。
不为繁华易匠心、为诸君共勉、
网友评论