Android代码故事第一回,平均间隔的按钮
我们的APP新做了一个放操作按钮的界面,老板要求简洁美观有内涵,按钮要均匀分布,于是参考之前的实现,设计MM给了一张图,像这样:
|==============================================|
|==========[Button]==========[Button]==========|
|==========[Button]==========[Button]==========|
|==============================================|
当然设计MM给的是高清图片,这里只是示意一下。经过分析,需求应该是这样的:两个按钮需要排列在一行里,要求他们之间的间距、以及按钮和屏幕边缘的间距要相等,并且要撑满整个屏幕宽度。
看来并不是什么难事,利用LinearLayout的特性,使用layout_weight使得占位View大小相同,如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"> <View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/> <ImageView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:src="@drawable/record_start"
android:gravity="center_horizontal"/> <View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/> <ImageView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:src="@drawable/game"
android:gravity="center_horizontal"
/> <View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</RelativeLayout>
Android Layout XML
效果图如下:
虽然引入了占位View,不那么优雅,但看起来很完美。
然而实际情况要复杂一点,每个按钮下面还有文字,添加上文字后效果如下:
依然看起来很完美,然后问题来了,按下Play按钮之后,它就会变成另一个按钮"Play again":
可以看到,两个按钮的位置与原来比有一点细微的偏差,因为第一个按钮由于字符串的变化而变宽了。之前没有考虑到按钮宽度不同的情况,他们之间的间距即使相等,也不会产生均匀分布的效果。但需要注意的是,按钮图片的宽度必须是相等的,否则无论如何都达不到均匀分布的视觉效果。
于是需求重新定义:每个按钮的X轴中心要正好在整个屏幕的N分之一处,N=按钮数量+1。
我们来研究一下用LinearLayout的weight能不能实现这个需求:
显然之前使占位View宽度相等的方法是不可行的,想要利用weight,那么就要找到宽度的一种比例上的关系,按钮之间的间距并不是固定的,固定的是他们中心的间距。但LinearLayout中所有View都是线性排列的,并没有像RelativeLayout中两个子View之间的关系来实现两个View的相对居中。
当然,有很多种复杂办法可以实现这个需求,比如用RelativeLayout在View绘制完成后,根据按钮的宽度和屏幕的宽度,用代码计算出margins值再设置给按钮;还可以自定义View计算出这个位置,这种方式应该是最正统的方式,但显得有些过于“小题大做”,并且定义一个有意义的自定义View并不是一件简单的事情。
还是回到LinearLayout,想实现需求必须要解决居中的问题,居中其实是所有View都有的功能,View的gravity属性能实现内容的居中,那么怎么利用这个属性呢?想要让按钮老实地待在屏幕的三分之一处,只能让这个点正好是某个View的二分之一处,那么其实这是一个数学问题。
假设按钮的图片宽度为w,屏幕宽度为W,间距长度L=(W-2w)/3,边缘的View宽度为L/2,而按钮实际宽度为L+w,于是两者的比例是(L/2):(L+w)。代入w=32dp,W=360dp,得到比例约等于5:13。于是代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <LinearLayout
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_centerVertical="true"> <View
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#ffaa00"
android:layout_weight="5"/> <TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:drawableTop="@drawable/ic_action_start"
android:gravity="center_horizontal"
android:layout_weight="13"
android:background="#00ff80"
android:text="Play again"/> <TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:drawableTop="@drawable/ic_action_stop"
android:gravity="center_horizontal"
android:layout_weight="13"
android:background="#4490a0"
android:text="Stop"/> <View
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#ffaa00"
android:layout_weight="5"/>
</LinearLayout>
<LinearLayout
android:id="@+id/layout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/layout1"
android:layout_centerVertical="true"> <View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_action_start"
android:gravity="center_horizontal"
android:text="Play"/> <View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_action_stop"
android:gravity="center_horizontal"
android:text="Stop"/> <View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</RelativeLayout>
Android Layout XML
问题初步解决,可以忽悠老板了。问题本身并没有完美解决,因为安卓的碎片化,屏幕宽度并不一定是360dp,如果你以为是这样,会有各种奇葩的设备给你会心一击,这也是不能用写死margin的方法的原因。用了这个方法的代码真的能上线么,我们来考虑一下各种屏幕宽度的情况,将使W=[300, 400]代入公式,得到下面的表:
其中按比例L/2就是weight=5的实际宽度,按比例L+w就是weight=13的实际宽度,偏差是按钮和屏幕的间距与两个按钮之间间距的差,反应了三等分的精确程度,可以看到偏差在屏幕宽度为300dp时仅仅是3dp左右。
所以结论是,真的可以忽悠老板。
当然,至此并没有完美解决问题,但用了最少的代码和时间达到了次优的效果,这个间距又不是生死功能,所以到此为止就算开发成功了。
后来还发现一个好处,就是当一个按钮不可见,visibility设置为GONE的时候,正好另一个按钮可以居中显示。
Android代码故事第一回,平均间隔的按钮的更多相关文章
- 《代码的第一行——Android》封面诞生
<代码的第一行--Android>已经上市近一个月,现在的情况是相当不错的销售,也特别感谢众多朋友的支持. 其实一本好书,假设你想卖.除了给予外力所要求的内容.封面设计是至关重要的,这本书 ...
- Volley使用指南第一回(来自developer.android)
最近闲来想看看android网络方面的东西.google在2013年发布了一个叫做Volley的网络请求框架,我看了一下官网,居然在training里面就有教程.首先,英文的东西看着 还是挺不爽的,特 ...
- 想写个小说,关于C#的,名字就叫《原Csharp》吧 (第一回 买书未成炁自生 惶惶回屋遇老翁)
以前也有写过一些小说,但是总是写写停停的,因为忙于项目和其他事情,总是耽搁很久(真的是很久)才会继续动两笔,所以我想先在这里以随笔的方式写个关于C#异世界的小故事吧,更新随缘,也稍微能让自己轻松些. ...
- android代码片段二
1.Android拦截短信 一.AndroidManifest.xml <uses-permission android:name="android.permission.RECE ...
- Android精通教程-第一节Android入门简介
前言 大家好,给大家带来Android精通教程-第一节Android入门简介的概述,希望你们喜欢 每日一句 If life were predictable it would cease to be ...
- Android代码规范
Android代码规范——文章来源<IT蓝豹>http://itlanbao.com/preview.aspx#1,0 [-]一Import的次序二缩进Indentation总则示例代码规 ...
- 浅谈android代码保护技术_ 加固
浅谈android代码保护技术_加固 导语 我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk,结果被人反编译了,那心情真心不舒服.虽然我们混淆,做到native层,但 ...
- Java&Android代码规范
项目中直接导入Square的代码风格文件.(不导入Google的原因是Square同时提供了Java和Android两套统一风格,Google只提供了一套) Square Code Styles Go ...
- Android studio开发-第一个应用
Android studio开发-第一个应用 上效果图 1.先创建布局文件 firstbutton.xml 代码 <?xml version="1.0" encoding=& ...
随机推荐
- office project 激活
office project 2010激活方式: 图上中,箭头位置,可能没激活,需要软件激活 ( mini-KMS Activator(Office2010激活工具) V1.2 绿色版 ) 激活方式如 ...
- asp.net中如何防止用户重复点击提交按钮
asp.net中如何防止用户重复点击提交按钮 asp.net 中防止因为网速慢等影响交互的问题导致用户可能点击多次提交按钮,从而导致数据库中出现多条重复的记录,经过亲自验证在网上找的方法,找到两个 ...
- spring mvc 删除返回字符串中值为null的字段
在spring的配置文件中进行一下配置: <bean class="org.springframework.web.servlet.mvc.method.annotation.Requ ...
- [ActionScript 3.0] 获取随机颜色
import flash.display.MovieClip; import flash.geom.ColorTransform; //方法一 var red:Number = Math.random ...
- Codeforces 28C [概率DP]
/* 大连热身D题 题意: 有n个人,m个浴室每个浴室有ai个喷头,每个人等概率得选择一个浴室. 每个浴室的人都在喷头前边排队,而且每个浴室内保证大家都尽可能均匀得在喷头后边排队. 求所有浴室中最长队 ...
- 03-c#入门(简易存款利息计算器v1.0)
本想把练习题做了的结果放上来,不过发现附录是有答案的,就算了吧,自己做了没问题就行了哈.之前提到过,要是有朋友有想法,需要做小工具我可以帮忙实现,不过貌似大家都很忙.SO,自己学完第4章后,决定做一个 ...
- AX 2012 在Grid 中添加image标识状态
refer to :http://kiwiaxguy.blogspot.hk/2013/10/displaying-image-on-form-grid-in.html
- iscroll4 捕捉元素开发手机焦点图滑动效果
html标准代码格式 <div id="wrapper"> <div id="scroller" > <ul id="t ...
- python 核心编程课后练习(chapter 6)
6-1 #6-1 #help(string) import string str = "helloworld" substr = "h1e" if string ...
- 如何定位Sharepoint网站集所在的w3wp进程
方法1. 直接开始运行,输入cmd,再输入iisapp可以列出当前所有IIS中的WebApplication所对应的w3wp.exe进程,后面都有一个进程号标识,在VS中调试的时候附加到对应进 ...