2017年2月16日星期四

700万小时搞定最小数独问题(ZT)

        三位爱尔兰数学家在2012年初发表了一篇论文,证明了数独至少需要 17 个初始数字才有唯一解。这个问题很难吗?其实一点也不,计算机才花了 700 万小时的 CPU 时间(CPU时间指CPU上执行指定代码的时钟周期数乘以每个时钟周期的时间长度)就搞定了这道数独题。这 700 万个小时它了做了什么?是三位数学家的方法很笨才导致算了这么久吗?实际上,这个时间已经不算长了。看看死理性派的详细介绍你就知道了。

数独游戏和长久以来的世界难题

        18 世纪末,瑞士数学家欧拉发明了一种叫做“拉丁方阵(Latin Square)”的游戏。虽然最初这个游戏并没有风靡起来,但随着时间的推移,在 20 世纪 70 年代的美国,这个游戏以“数字拼图(Number Place)”的名字迅速流行起来,之后逐渐流传到日本、英国,到现在已经成为了红遍全球的智力游戏。
数独游戏基本规则是这样的:在一个九宫格中给出一些初始数字。玩家需要在九宫格内填入缺失的数字(1 - 9),保证:
每一行的 9 个数字各不相同
每一列的 9 个数字各不相同
每一个用粗线标识出的 3 × 3 的小正方形内 9 个数字也各不相同
        虽然规则非常简单,但其中包含的信息却毫不简单。数学家 Bertram Felgenhauer 在 2005 年证明,数独的解共有 9! × 722 × 27 × 27,704,267,971 种不同的可能组合,上面这个乘式的最后一个数还是一个质数。
一个经典的数独。图像来源:wikipedia
一个经典的数独。
        而如此多变的变化,无疑也给数学家们出了不少难题。其中一个被讨论了很久的问题是, 至少给定多少个初始数字,数独才会有唯一解? 此前已经有人给出了一些包含 17 个初始数字的数独,并利用计算机证明了其解是唯一的(对于某个给定了 17 个初始数字的数独,计算机枚举了所有可能的排列情况,只找到一个解),从而证明了 17 个初始数字的数独是可以存在唯一解的。但是长久以来都没有人知道, 16 个初始数字的数独是否存在唯一解。终于,在 2012 的元旦,都柏林大学(University College Dublin)的数学家们给出了 答案:16 个初始数字的数独不存在唯一解。

有没有解试出来

        消息一出,媒体争相报道,报道中不乏复杂的算法、超级计算机等“虽然不知道在说什么,但看起来很厉害”的词汇。事实上,研究人员用来证明这个问题的方法用一个字就可以总结,那就是——试。
        解决这个问题几位数学家最初的想法非常可爱: 只要把每一种有 16 个初始数字的数独都尝试着填一遍,自然就知道答案了。 但很可惜,因为数独的组合实在是太多了,所以即使是现在最快的计算机,也不可能在我们的有生之年穷尽所有的组合。因此,必须用一些数学的方法来减少尝试的次数,这个想法才能够实现。
他们发现,数独虽然有很多种可能的组合,但是其中一些其实是等价的。如下图,可以看到交换第一列和第二列对整个数独并没有影响。实际上任意一个合法数独的解交换两列后,都可以构成一个新的合法数独,而这个新数独和原数独就可以看做是等价的。
两种等价的数独组合
两种等价的数独组合
三位数学家总结了数独的 4 种等价变换:
⒈ 列与列的重新排列(例如上图)
⒉ 行与行的重新排列
⒊ 数字 1 到 9 的重新排列。如把原先是 1 的位置都填上 2,然后把原先是 2 的位置都填上……直到把原先是 9 的位置都填上 1 等
⒋ 网格的变换。如整个数独顺时针旋转90度,整个数独做镜像对称等
在 2006 年已经有数学家证明,排除以上几种重复后,数独总共有 5,475,730,538 个等价类。因为每个等价类里的任意一种情况都可以通过这个等价类中的其它情况经由以上 4 种变换得到,所以对每个等价类来说,我们只要考虑一种情况即可。如此一来,有非常多的组合都被我们直接排除了,计算量大大减小。

让枚举量少一点,再少一点

        虽然等价类的数量已经降低到了可以接受的范围,但问题还远没有结束。因为在选择了某个等价类中的一种情形之后,我们还需要验证这个情形的 81 个数字中是否可以选出 16 个,使得以这 16 个数为初始数字的数独有唯一解。
如果检查所有的可能情况,对于每一个等价类,我们要检查的次数就是:
/gkimage/ld/cs/bh/ldcsbh.png这显然很不幸:好不容易通过排除等价变换的方法把计算量减下去,怎么能在这里再加回来呢!所以这又需要数学家再做一些工作,把 3.4 × 10 16 这个数减小,让枚举量少一点,再少一点。
        因此,几位数学家利用了 “不可避免集”的概念:如下图所示,如果表示颜色的 4 个数字中任何一个都没有在初始数字中给出,那么这个数独一定没有唯一解——因为在没有给出的情况下这 4 个数字都是由玩家填进去的,玩家既可以以左图的方式填入这 4 个数字,也可以以右图的方式填入,而得到的两个解都是合法的。具有这种属性的数个方格就叫做不可避免集,一旦出现了不可避免集,我们就必须要在其中至少选出一个格子用来填写初始数字。
不可避免集
不可避免集

不可避免集大大化简计算量

        在论文中,数学家们采用了 Ed Russell 总结的一套不可避免集的模板,总共记录了 525 种不同的不可避免集。因为一开始所说的 4 种等价变换对不可避免集也适用,所以他们对不可避免集进行了一些标准化的处理,以保证这 525 种不可避免集互相之间不能通过 4 种等价变换得到。
        此时,枚举算法就被改造成这样:数学家给所有的不可避免集都设定一个状态,分为“被击中”或“未被击中”两种。初始时九宫格 81 个方格内都没有填入数字,所有不可避免集的初始状态均为“未被击中”。之后开始每次选择一个最小的未被击中的不可避免集,枚举其中的每个格子。即每次选择不可避免集中的一个格子填充初始数字,直至试完不可避免集中的所有空格。同时将这个不可避免集标记为“被击中”状态,每次枚举都有 4 种可能。
● 如果这个格子也出现在了其它不可避免集中,那么将这些被涉及到的不可避免集也标记为“被击中”状态;
● 如果枚举了 16 个格子后还有不可避免集未被击中,说明以这 16 个格子为初始状态的数独一定没有唯一解;
● 恰好枚举了 16 个格子后所有的不可避免集全部被击中;
● 如果枚举了不到 16 个格子后所有不可避免集已经全部被击中,则从剩下的所有格子中再枚举几个格子使初始填充了数字的格子达到 16 个。
        完成上面这个工作后,就要用解数独的程序来验证所有枚举的情况是否有唯一解。为了进一步加快枚举速度,数学家们还加入了一些可行性剪枝和最优化剪枝,如提前判断“当前情况下已经不可能击中所有不可避免集”并终止枚举等。
        在这一系列优化之后,算法的复杂度终于降低到了可以接受的范围内。但即使这样,整个计算过程还是耗费了 700 万小时的 CPU 时间。幸而这个算法最终给出了一个确定的结果:所有仅包含 16 个初始数字的数独,都不存在唯一解!

暴力与美学的结合

        当然,上述结果的正确性还有待其他科学家进一步验证,因为算法耗时极高,所以验证过程也需要花费比较长的时间。但无论这次 3 位数学家给出的结论正确与否,随着验算结果的公布,这个问题终将得到一个解答。
        粗略看来,这个算法的实现是非常暴力和机械化的:尝试每一种可能的情况。但是在实现的过程中,数学家们又在借助于数学的力量,不断地试图减少枚举的数量,最终将不可能的事情化为了现实。怪不得西澳大利亚大学的数学家 Gordon Royle 这样评价道:“这个挑战性的问题让人们把计算的能力和数学的技巧发挥到了极限,这就像是在攀登最高耸的山峰。”

2017年2月2日星期四

如何集成 Tomcat 插件到 Eclipse?

  1. 下载 Tomcat
        作者选择的是 Tomcat7,下载地址:http://tomcat.apache.org/download-70.cgi
        2. 安装 Tomcat
        解压缩第 1 步的 apache-tomcat-7.0.75.zip,作者把它解压缩在 E 盘 setup目录下。右键点击我的电脑,选择属性->高级->环境变量->新建系统变量,变量名TOMCAT_HOME,变量值输入 E:\setup\apache-tomcat-7.0.75->确定。
        3. 下载 Tomcat Eclipse 插件
        下载地址 http://www.eclipsetotale.com/tomcatPlugin.html。最新的 releaseNotesV331 可以支持到 Tomcat 7(tomcatPluginV33.zip 可以支持 Eclipse 3.1, 3.2, 3.3, 3.4, 3.5, 3.6 和 Tomcat 4.x, 5.x, 6.x, 7.x。
        4. 安装 Tomcat 插件
        将上一步得到的 tomcatPluginV331.zip 解压缩,将解压缩后得到的 com.sysdeo.eclipse.tomcat_3.3.1 文件拷贝到 eclipse 根目录下的 plugins 目录中。重启 eclipse,工具栏里出现图标Eclipse工具栏Tomcat的图标证明已经安装成功。
        5. Eclipse Tomcat 配置
        eclipse->Window->Preferences->Tomcat,勾选Version 7.x,Tomcat home 选择第二步的安装目录。点击确定按钮。
        6. 部署 JEE 项目到 Tomcat
        右键点击项目名,Properties->Tomcat->确认 Is a Tomcat Project 被勾选后点击 OK 按钮,%Tomcat%/conf/Catalina/localhost 下会有 *.xml 文件生成。

2017年2月1日星期三

Apache与Tomcat之间的区别和联系

Apache 和 Tomcat 都是web网络服务器,两者既有联系又有区别,在进行HTML、PHP、JSP、Perl等开发过程中,需要准确掌握其各自特点,选择最佳的服务器配置。

apache是web服务器(静态解析,如HTML),tomcatjava应用服务器(动态解析,如JSP、PHP)
tomcat只是一个servlet(jsp也翻译成servlet)的容器,可以认为是apache的扩展,但是可以独立于apache运行。
两者从以下几点可以比较的: 
1、两者都是apache组织开发的 
2、两者都有HTTP服务的功能 
3、两者都是开源免费的 

联系
1)Apache是普通服务器,本身只支持html即普通网页,可以通过插件支持php,还可以与Tomcat连通(Apache单向连接Tomcat,就是说通过Apache可以访问Tomcat资源,反之不然)。
2)Apache只支持静态网页,但像asp、jsp、php、cgi等动态网页就需要Tomcat来处理。
3)Apache和Tomcat整合使用:
如果客户端请求的是静态页面,则只需要Apache服务器响应请求;
如果客户端请求动态页面,则是Tomcat服务器响应请求,将解析的JSP等网页代码解析后回传给Apache服务器,再经Apache返回给浏览器端
这是因为jsp是服务器端解释代码的,Tomcat只做动态代码解析,Apache回传解析好的静态代码,Apache+Tomcat这样整合就可以减少Tomcat的服务开销 。 
4)Apache和Tomcat是独立的,在同一台服务器上可以集成。

区别
Apache是有C语言实现的,支持各种特性和模块从而来扩展核心功能;Tomcat是Java编写的,更好的支持Servlet和JSP。
1、Apache是Web服务器,Web服务器传送(serves)页面使浏览器可以浏览,Web服务器专门处理HTTP请求(request),但是应用程序服务器是通过很多协议来为应用程序提供 (serves)商业逻辑(business logic)。

Tomcat是运行在Apache上的应用服务器,应用程序服务器提供的是客户端应用程序可以调用(call)的方法 (methods)。它只是一个servlet(jsp也翻译成servlet)容器,可以认为是Apache的扩展,但是可以独立于apache运行。

2、Apache是普通服务器,本身只支持html静态普通网页。不过可以通过插件支持PHP,还可以与Tomcat连通(单向Apache连接Tomcat,就是说通过Apache可以访问Tomcat资源,反之不然),Tomcat是jsp/servlet容器,同时也支持HTML、JSP、ASP、PHP、CGI等,其中CGI需要一些手动调试,不过很容易的。

3、Apache侧重于http server,Tomcat侧重于servlet引擎,如果以standalone方式运行,功能上
Tomcat与apache等效支持JSP,但对静态网页不太理想。

4、Apache可以运行一年不重启,稳定性非常好,而Tomcat则不见得。

5、 首选web服务器是Apache,但Apache解析不了的jsp、servlet才用tomcat。

6、Apache是很最开始的页面解析服务,tomcat是后研发出来的,从本质上来说tomcat的功能完全可以替代Apache,但Apache毕竟是tomcat的前辈级人物,并且市场上也有不少人还在用Apache,所以Apache还会继续存在,不会被取代,apache不能解析java的东西,但解析html速度快。


两者例子:
apache是一辆车,上面可以装一些东西如html等,但是不能装水,要装水必须要有容器(桶),而这个桶也可以不放在卡车上,那这个桶就是TOMCAT。


两者整合:
Apache是一个web服务器环境程序,启用他可以作为web服务器使用不过只支持静态网页,不支持动态网页,
如asp、jsp、php、cgi。
如果要在Apache环境下运行jsp就需要一个解释器来执行jsp网页,而这个jsp解释器就是Tomcat。
那为什么还要JDK呢?因为jsp需要连接数据库的话就要jdk来提供连接数据库的驱程,所以要运行jsp的web服务器平台就需要APACHE+TOMCAT+JDK

整合的好处:
如果客户端请求的是静态页面,则只需要Apache服务器响应请求。
如果客户端请求动态页面,则是Tomcat服务器响应请求。
因为jsp是服务器端解释代码的,这样整合就可以减少Tomcat的服务开销。

致李显龙总理的一封公开信。

敬爱的李显龙总理,

    本公司(PIABIA)在Blk 824,Jurong west street 81租下了一间HDB超市(mini-mart),本来卖酒名正言顺,结果莫名其妙地受到HDB杯葛,导致一直申请不到酒的牌照。而隔壁Blk 825同样类似的HDB超市则能拥有酒的牌照(License)。
    新加坡被评为经济自由度第2高的国家和地区,酒牌照申请的不平等待遇明显与新加坡的经济自由度不符,也容易滋生政府腐败和权钱交易。
    本来酒牌照的申请是通过police(警察局)处理的,现在还得经过HDB批准。多了一道莫须有的关卡,就难以避免权力的滥用和政府效率的降低。
    不管在中国、美国、日本、德国还是世界各地,超市卖酒都是天经地义的事,既便民又亲民,这也是符合市场经济规律的。总不能在组屋超市里卖奢侈品吧。
    希望李显龙总理能够关注我们小老百姓们的民生,遏制懒政,建立一个“民有、民治和民享”的优秀政府。

2017年1月9日星期一

蟑螂杀手:扁头穴蜂(寄生蜂,黄蜂)

(泛科学)寄生虫-扁头穴蜂-2
扁头穴蜂(Ampulex compressa
  • 分类:昆虫类
  • 体长:20 mm
  • 宿主:蟑螂
  • 分布:热带地区
    椭圆形躯干映着黑色光泽,爬行时发出叽擦叽擦声的脚,纤细又动个不停的长触须,跑得飞快,偶尔飞一飞。这只让我们引起生理性嫌恶的昆虫,便是蟑螂。多数的蟑螂住在森林中,但举凡有人生活的环境都有其踪迹。其环境适应力,可用「即使整个地球上的人类都灭绝了,蟑螂也绝不会灭绝」这句话来形容。
    但连这样顽强的蟑螂也有天敌,那就是扁头穴蜂[又称翡翠蟑螂穴蜂(emerald cockroach wasp)]。其犀利的外骨骼透着青绿色的金属光泽,这种小型蜂广泛地分布在热带区域(包括新加坡)。这种蜂将活生生的蟑螂当作幼虫的饲料而进行繁殖,其手段可说是残忍至极。
    扁头穴蜂的雌蜂会在蟑螂身上刺两针。首先会在大面积的胸部神经节部分刺第一针,使蟑螂停止行动。一旦动作停止,就会对头部的脑进行第二次精确的刺击。头部被刺击的蟑螂会放弃逃窜,且开始有四肢摊张现象。此乃因流入脑内的毒素,有麻痹反射性逃离的效果。当蟑螂变老实之后,蜂就会用颚将蟑螂的两只触角削短,这动作究竟是为了要从断掉的触角吸啜体液,以便补充于格斗中消耗的体力;还是为了要调整注入蟑螂体内的毒液量,以维持其生死参半的状态,到目前都还不清楚。
(泛科学)寄生虫-扁头穴蜂-4
在此之后,穴蜂会牵着蟑螂的触角将其带回巢穴内。封锁反射性逃避的原因,是要让体型较大的蟑螂维持足可靠自己步行的能力。蟑螂乖乖地被牵着走向穴蜂巢穴后,其身体表面就会被产下的卵附着。穴蜂为了不让其他动物将蟑螂吃掉,会将巢穴入口用石头塞起来,并就此飞去。
从卵孵化出来的幼虫,会将蟑螂的腹部咬破后入侵其体内,在那儿一边享用内脏一边成长。不久在蟑螂体内化为蛹的幼虫,于破蛹后就会从巢穴飞出去,留下身体被吃干抹净,徒留外骨骼的蟑螂尸体。一边活着一边内脏被咬去的蟑螂,会不会很痛苦呢?不是当事者的我们很难知道。像这样作为宿主的蟑螂被扁头泥蜂寄生后必然死亡的情形,通称为捕食性寄生。

How to become a Singpore UBER driver?

Here are the requirements to be an Uber Partner:

1) Singapore PR or Citizen
2) Aged 25 or older
3) Have no been imprisoned for more than 7 days
4) Have a class 3 driving license

If you do pass the four requirements, you may go ahead and register at https://partners.uber.com/home/.

Register a company with ACRA with code 49219 (for PASSENGER LAND TRANSPORT NEC), or add business code 49219 to your existing company. To do so, go to:
ACRA at International Plaza, 10 Anson Road #05-01, or register your company online by going to: http://t.uber.com/ubersgbizfile

If you have your own vehicle, you would have to convert your private vehicle to a commercially registered vehicle. What we would need you to do is switch to commercial insurance on your vehicle (Tip: Negotiate to retain your NCD when changing your insurance plan to commercial) Then convert your vehicle to a Z10 or Z11 category. You could visit the LTA at 1 Hampshire Road or 10 Sin Ming Drive to do this. Fill out form M01 (Application Form for Transfer of Vehicle) to transfer ownership of your vehicle to your company. Submit your M01 form to change the vehicle type of your car from P10/P11 to Z10/Z11.

Rent a vehicle from a car rental company. You must make sure that the your rented vehicle has:
- Comprehensive commercial insurance (including service and maintenance)
- Vehicle registration as a Z10 or Z11 vehicle
- Ask an Uber team member if you need some suggestions on rental partners, or visit www.sgcarmart.com or www.drive.sg

The company now that we are recommending is Krys (Lion City Rentals) at 84333974 (mobile) during 0930-1730hrs or email them at rentals@lioncityrentals.net

Come to our office to get activated and start driving!

Time: Mon/Tue/Wed/Fri, 10am-5pm
Location:Mid View City, #01-14, 18 Sin Ming Lane 573960

You’ll need to bring:
- Your NRIC and a valid driver’s license;
- Your business registration from ACRA showing business code 49219;
- Proof of commercial insurance for your vehicle;
- Vehicle log showing Z10 or Z11 registration
- Within one month of being activated, we’ll need you to submit a signed mandatory Statutory Declaration form (please see attached)
[Optional] Register to be a relief driver here: http://t.uber.com/ubersgdriverelief

2017年1月4日星期三

Android系统五大布局(Layout)详解

      Android系统应用程序一般是由多个Activity组成,而这些Activity以视图的形式展现在我们面前,视图都是由一个一个的组件构成的。组件就是我们常见的Button、TextEdit等等。那么我们平时看到的Android手机中那些漂亮的界面是怎么显示出来的呢?这就要用到Android的布局管理器了,网上有人比喻得很好:布局好比是建筑里的框架,组件按照布局的要求依次排列,就组成了用于看见的漂亮界面了。
      在分析布局之前,我们首先看看控件:Android中任何可视化的控件都是从android.veiw.View继承而来的,系统提供了两种方法来设置视图:第一种也是我们最常用的的使用XML文件来配置View的相关属性,然后在程序启动时系统根据配置文件来创建相应的View视图。第二种是我们在代码中直接使用相应的类来创建视图。
     如何使用XML文件定义视图:
      每个Android项目的源码目录下都有个res/layout目录,这个目录就是用来存放布局文件的。布局文件一般以对应activity的名字命名,以 .xml 为后缀。在xml中为创建组件时,需要为组件指定id,如:android:id="@+id/名字"系统会自动在gen目录下创建相应的R资源类变量。 
    如何在代码中使用视图:  
     在代码中创建每个Activity时,一般是在onCreate()方法中,调用setContentView()来加载指定的xml布局文件,然后就可以通过findViewById()来获得在布局文件中创建的相应id的控件了,如Button等。
 如:

  1. private Button btnSndMag;  
  2. public void onCreate(Bundle savedInstanceState) {  
  3.     super.onCreate(savedInstanceState);  
  4.     setContentView(R.layout.main);  // 加载main.xml布局文件  
  5.     btnSndMag = (Button)this.findViewById(R.id.btnSndMag); // 通过id找到对于的Button组件  
  6.     ....  
  7. }  
  
  下面我们来介绍Android系统中为我们提供的五大布局:LinearLayout(线性布局)、FrameLayout(单帧布局)、AbsoluteLayout(绝对布局)、TablelLayout(表格布局)、RelativeLayout(相对布局)。其中最常用的的是LinearLayout、TablelLayout和RelativeLayout。这些布局都可以嵌套使用。
(1)LinearLayout 线性布局
  线性布局是按照水平或垂直的顺序将子元素(可以是控件或布局)依次按照顺序排列,每一个元素都位于前面一个元素之后。线性布局分为两种:水平方向和垂直方向的布局。分别通过属性android:orientation="vertical" 和 android:orientation="horizontal"来设置。
 android:layout_weight 表示子元素占据的空间大小的比例,有人说这个值大小和占据空间成正比,有人说反比。我在实际应用中设置和网上资料显示的刚好相反,这个问题后面会专门写一篇文章来分析。现在我们只需要按照正比例来设置就可以。 
例如下面我们实现一个如图所示的简易计算器界面:
代码:

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:background="#FFFFFF"  
  7.     tools:context=".MainActivity" >  
  8.   
  9.     // 这里第一行显示标签为一个水平布局  
  10.     <LinearLayout  
  11.         android:layout_width="match_parent"  
  12.         android:layout_height="wrap_content"  
  13.         android:orientation="horizontal" >  
  14.         <EditText  
  15.             android:id="@+id/msg"  
  16.             android:inputType="number"  
  17.             android:layout_width="match_parent"  
  18.             android:layout_height="wrap_content"  
  19.             android:text="">  
  20.         </EditText>      
  21.     </LinearLayout>  
  22.       
  23.     // 第二行为 mc m+ m- mr 四个Button构成一个水平布局  
  24.     <LinearLayout  
  25.         android:layout_width="match_parent"  
  26.         android:layout_height="wrap_content"  
  27.         android:orientation="horizontal" >  
  28.         <Button  
  29.             android:layout_width="match_parent"  
  30.             android:layout_height="wrap_content"  
  31.             android:text="mc" android:layout_weight="1">  
  32.         </Button>  
  33.         <Button  
  34.             android:layout_width="match_parent"  
  35.             android:layout_height="wrap_content"  
  36.             android:text="m+" android:layout_weight="1">  
  37.         </Button>  
  38.         <Button  
  39.             android:layout_width="match_parent"  
  40.             android:layout_height="wrap_content"  
  41.             android:text="m-" android:layout_weight="1">  
  42.         </Button>  
  43.         <Button  
  44.             android:layout_width="match_parent"  
  45.             android:layout_height="wrap_content"  
  46.             android:text="mr" android:layout_weight="1">  
  47.         </Button>  
  48.     </LinearLayout>  
  49.       
  50.     // 同上 C +/-  / * 四个Button构成一个水平布局  
  51.       <LinearLayout  
  52.           android:layout_width="match_parent"  
  53.           android:layout_height="wrap_content"  
  54.           android:orientation="horizontal" >  
  55.           <Button  
  56.               android:layout_width="match_parent"  
  57.               android:layout_height="wrap_content"  
  58.               android:layout_weight="1"  
  59.               android:text="C" >  
  60.           </Button>  
  61.           <Button  
  62.               android:layout_width="match_parent"  
  63.               android:layout_height="wrap_content"  
  64.               android:layout_weight="1"  
  65.               android:text="+/-" >  
  66.           </Button>  
  67.           <Button  
  68.               android:layout_width="match_parent"  
  69.               android:layout_height="wrap_content"  
  70.               android:layout_weight="1"  
  71.               android:text="/" >  
  72.           </Button>  
  73.           <Button  
  74.               android:layout_width="match_parent"  
  75.               android:layout_height="wrap_content"  
  76.               android:layout_weight="1"  
  77.               android:text="*" >  
  78.           </Button>  
  79.       </LinearLayout>  
  80.       
  81.       <LinearLayout  
  82.         android:layout_width="match_parent"  
  83.         android:layout_height="wrap_content"  
  84.         android:orientation="horizontal" >  
  85.         <Button  
  86.             android:layout_width="match_parent"  
  87.             android:layout_height="wrap_content"  
  88.             android:text="7" android:layout_weight="1">  
  89.         </Button>  
  90.         <Button  
  91.             android:layout_width="match_parent"  
  92.             android:layout_height="wrap_content"  
  93.             android:text="8" android:layout_weight="1">  
  94.         </Button>  
  95.         <Button  
  96.             android:layout_width="match_parent"  
  97.             android:layout_height="wrap_content"  
  98.             android:text="9" android:layout_weight="1">  
  99.         </Button>  
  100.         <Button  
  101.             android:layout_width="match_parent"  
  102.             android:layout_height="wrap_content"  
  103.             android:text="-" android:layout_weight="1">  
  104.         </Button>  
  105.     </LinearLayout>  
  106.       
  107.     <LinearLayout  
  108.         android:layout_width="match_parent"  
  109.         android:layout_height="wrap_content"  
  110.         android:orientation="horizontal" >  
  111.         <Button  
  112.             android:layout_width="match_parent"  
  113.             android:layout_height="wrap_content"  
  114.             android:layout_weight="1"  
  115.             android:text="4" >  
  116.         </Button>  
  117.         <Button  
  118.             android:layout_width="match_parent"  
  119.             android:layout_height="wrap_content"  
  120.             android:layout_weight="1"  
  121.             android:text="5" >  
  122.         </Button>  
  123.         <Button  
  124.             android:layout_width="match_parent"  
  125.             android:layout_height="wrap_content"  
  126.             android:layout_weight="1"  
  127.             android:text="6" >  
  128.         </Button>  
  129.         <Button  
  130.             android:layout_width="match_parent"  
  131.             android:layout_height="wrap_content"  
  132.             android:layout_weight="1"  
  133.             android:text="+" >  
  134.         </Button>  
  135.     </LinearLayout>  
  136.       
  137.     // 最外层是一个水平布局,由左边上面一行1 2 3三个Button,下面一行的0 . 两个Button 和 右边的=构成  
  138.      <LinearLayout android:orientation="horizontal"  
  139.         android:layout_width="match_parent"  
  140.         android:layout_height="wrap_content">  
  141.         // 这里 1 2 3 和 下面的 0 . 构成一个垂直布局  
  142.         <LinearLayout android:orientation="vertical"  
  143.             android:layout_weight="3"  
  144.             android:layout_width="wrap_content"  
  145.             android:layout_height="wrap_content">  
  146.             // 这里的 1 2 3 构成一个水平布局  
  147.             <LinearLayout android:orientation="horizontal"  
  148.                 android:layout_width="match_parent"  
  149.                 android:layout_height="wrap_content">  
  150.                 <Button  
  151.                     android:layout_width="wrap_content"  
  152.                     android:layout_height="wrap_content"  
  153.                     android:layout_weight="1"  
  154.                     android:text="1"></Button>  
  155.                 <Button  
  156.                     android:layout_width="wrap_content"  
  157.                     android:layout_height="wrap_content"  
  158.                     android:layout_weight="1"  
  159.                     android:text="2"></Button>  
  160.                 <Button  
  161.                     android:layout_width="wrap_content"  
  162.                     android:layout_height="wrap_content"  
  163.                     android:layout_weight="1"  
  164.                     android:text="3"></Button>  
  165.             </LinearLayout>  
  166.             // 这里的 0 和 . 构成一个水平布局,注意这里的android_weight参数设置  
  167.             <LinearLayout android:orientation="horizontal"  
  168.                 android:layout_width="match_parent"  
  169.                 android:layout_height="wrap_content">  
  170.                 <Button  
  171.                     android:layout_width="0px"  
  172.                     android:layout_height="wrap_content"  
  173.                     android:layout_weight="2"  
  174.                     android:text="0"></Button>  
  175.                 <Button  
  176.                     android:layout_width="0px"  
  177.                     android:layout_height="wrap_content"  
  178.                     android:layout_weight="1"  
  179.                     android:text="."></Button>  
  180.             </LinearLayout>     
  181.         </LinearLayout>  
  182.         // 这里一个单独Button构成的垂直布局  
  183.         <LinearLayout android:orientation="vertical"  
  184.             android:layout_weight="1"  
  185.             android:layout_width="wrap_content"  
  186.             android:layout_height="match_parent">  
  187.             <Button  
  188.                 android:layout_width="match_parent"  
  189.                 android:layout_height="match_parent"  
  190.                 android:text="="></Button>  
  191.         </LinearLayout>  
  192.      </LinearLayout>     
  193.   
  194. </LinearLayout>  
(2)TableLayout 表格布局
         表格布局,适用于多行多列的布局格式,每个TableLayout是由多个TableRow组成,一个TableRow就表示TableLayout中的每一行,这一行可以由多个子元素组成。实际上TableLayout和TableRow都是LineLayout线性布局的子类。但是TableRow的参数android:orientation属性值固定为horizontal,且android:layout_width=MATCH_PARENT,android:layout_height=WRAP_CONTENT。所以TableRow实际是一个横向的线性布局,且所以子元素宽度和高度一致。
       注意:在TableLayout中,单元格可以为空,但是不能跨列,意思是只能不能有相邻的单元格为空。
        在TableLayout布局中,一列的宽度由该列中最宽的那个单元格指定,而该表格的宽度由父容器指定。可以为每一列设置以下属性:
     Shrinkable  表示该列的宽度可以进行收缩,以使表格能够适应父容器的大小
     Stretchable 表示该列的宽度可以进行拉伸,以使能够填满表格中的空闲空间
     Collapsed  表示该列会被隐藏
TableLayout中的特有属性:
android:collapseColumns
        android:shrinkColumns
        android:stretchColumns = "0,1,2,3"// 表示产生4个可拉伸的列
Demo:我们想设计一个如下所以的一个三行三列的表格,但是第二行我们只想显示2个表格:

  1. "1.0" encoding="utf-8"?>  
  2. "http://schemas.android.com/apk/res/android"  
  •     android:orientation="vertical"  
  •     android:shrinkColumns="0,1,2"  // 设置三列都可以收缩    
  •     android:stretchColumns="0,1,2" // 设置三列都可以拉伸 如果不设置这个,那个显示的表格将不能填慢整个屏幕  
  •     android:layout_width="fill_parent"  
  •     android:layout_height="fill_parent" >      
  •     "fill_parent"  
  •         android:layout_height="wrap_content">  
  •           
  •             android:padding="10dp"  
  •             android:text="Button1">  
  •         
  •   
  •         
  •           
  •             android:padding="10dp"  
  •             android:text="Button2">  
  •         
  •   
  •           
  •             android:padding="10dp"  
  •             android:text="Button3">  
  •         
  •   
  •     
  •   
  •     "fill_parent"  
  •         android:layout_height="wrap_content">  
  •           
  •             android:padding="10dp"  
  •             android:text="Button4">  
  •         
  •   
  •         
  •           
  •             android:padding="10dp"  
  •             android:text="Button5">  
  •         
  •   
  •     
  •   
  •     "fill_parent"  
  •         android:layout_height="wrap_content">  
  •           
  •             android:padding="10dp"  
  •             android:text="Button6">  
  •         
  •        
  •           
  •             android:padding="10dp"  
  •             android:text="Button7">  
  •         
  •   
  •           
  •             android:padding="10dp"  
  •             android:text="Button8">  
  •         
  •   
  •     
  •   
  •   (3)RelativeLayout 相对布局
       RelativeLayout继承于android.widget.ViewGroup,其按照子元素之间的位置关系完成布局的,作为Android系统五大布局中最灵活也是最常用的一种布局方式,非常适合于一些比较复杂的界面设计。
       注意:在引用其他子元素之前,引用的ID必须已经存在,否则将出现异常。
    常用的位置属性:  

    1. android:layout_toLeftOf         该组件位于引用组件的左方  
    2. android:layout_toRightOf        该组件位于引用组件的右方  
    3. android:layout_above            该组件位于引用组件的上方  
    4. android:layout_below                该组件位于引用组件的下方  
    5. android:layout_alignParentLeft      该组件是否对齐父组件的左端  
    6. android:layout_alignParentRight     该组件是否齐其父组件的右端  
    7. android:layout_alignParentTop       该组件是否对齐父组件的顶部  
    8. android:layout_alignParentBottom    该组件是否对齐父组件的底部  
    9. android:layout_centerInParent       该组件是否相对于父组件居中  
    10. android:layout_centerHorizontal     该组件是否横向居中  
    11. android:layout_centerVertical       该组件是否垂直居中  
    Demo:利用相对布局设计一个如下图所示的界面:
    源码:

    1. xml version="1.0" encoding="utf-8"?>  
    2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:layout_width="fill_parent"  
    4.     android:layout_height="fill_parent" >  
    5.     <Button android:id="@+id/btn1"  
    6.         android:layout_width="wrap_content"  
    7.         android:layout_height="wrap_content"  
    8.         android:layout_centerInParent="true"  
    9.         android:layout_centerHorizontal="true"  
    10.         android:text="Button1"  
    11.         ></Button>  
    12.     <Button android:id="@+id/btn2"  
    13.         android:layout_width="wrap_content"  
    14.         android:layout_height="wrap_content"  
    15.         android:layout_toLeftOf="@id/btn1"  
    16.         android:layout_above="@id/btn1"  
    17.         android:text="Button2"  
    18.         ></Button>  
    19.     <Button android:id="@+id/btn3"  
    20.         android:layout_width="wrap_content"  
    21.         android:layout_height="wrap_content"  
    22.         android:layout_toRightOf="@id/btn1"  
    23.         android:layout_above="@id/btn1"  
    24.         android:text="Button3"  
    25.         ></Button>  
    26.     <Button android:id="@+id/btn4"  
    27.         android:layout_width="wrap_content"  
    28.         android:layout_height="wrap_content"  
    29.         android:layout_toRightOf="@id/btn2"  
    30.         android:layout_toLeftOf="@id/btn3"  
    31.         android:layout_above="@id/btn2"  
    32.         android:text="Button4"  
    33.         ></Button>  
    34. </RelativeLayout>  
    (4)FrameLayout 框架布局
     将所有的子元素放在整个界面的左上角,后面的子元素直接覆盖前面的子元素,所以用的比较少。
    (5) AbsoluteLayou 绝对布局
       绝对布局中将所有的子元素通过设置android:layout_x 和 android:layout_y属性,将子元素的坐标位置固定下来,即坐标(android:layout_x, android:layout_y) ,layout_x用来表示横坐标,layout_y用来表示纵坐标。屏幕左上角为坐标(0,0),横向往右为正方,纵向往下为正方。实际应用中,这种布局用的比较少,因为Android终端一般机型比较多,各自的屏幕大小。分辨率等可能都不一样,如果用绝对布局,可能导致在有的终端上显示不全等。

    除上面讲过之外常用的几个布局的属性:
    (1)layout_margin 
    用于设置控件边缘相对于父控件的边距
    android:layout_marginLeft
    android:layout_marginRight
    android:layout_marginTop
    android:layout_marginBottom

    (2) layout_padding 
    用于设置控件内容相对于控件边缘的边距
    android:layout_paddingLeft
    android:layout_paddingRight
    android:layout_paddingTop
    android:layout_paddingBottom

    (3) layout_width/height
    用于设置控件的高度和宽度
    wrap_content 内容包裹,表示这个控件的里面文字大小填充
    fill_parent 跟随父窗口
    match_parent

    (4) gravity 
    用于设置View组件里面内容的对齐方式
    top bottom  left   right   center等

    (5) android:layout_gravity  
    用于设置Container组件的对齐方式
    android:layout_alignTop 本元素的上边缘和某元素的的上边缘对齐
    android:layout_alignLeft 本元素的左边缘和某元素的的左边缘对齐
    android:layout_alignBottom 本元素的下边缘和某元素的的下边缘对齐
    android:layout_alignRight 本元素的右边缘和某元素的的右边缘对齐