Sunday, June 28, 2015

致青春 我的小学---- 赵千秋 我的挚爱

今天,终于打通了电话。没有之前,想想的那样,但是,在一瞬间,接到她打来的电话的时候,我还是没有出息的说不出话来!是的,时间过的很快,我们都变了。我们已经不在是以前的我们了!

物是人非。欲语泪先流。

一开始,真的是我没有似乎没有什么共同语言了。是的,毕竟我们已经分别这么多年了。很多事情,很多 比如:世界观 人生观 价值观 都已经变了!对于她而言 她的男朋友就是她现在的一切,以后的生活完全有她的男朋友做主了。她的男朋友就是她的天了。可以决定她的思维了,我真的是无法想象,她在也不是我喜欢的赵千秋了,因为,她已经为他改变的太多了。所以,我似乎一直活在自己的 海市蜃楼里面,当她问我 为什么要找她的时候,我真的很无语。我也不知道,就是自己的心里面想知道她的境况,想了解她现在过的怎么样。我不知道,我到底想要什么,就是一颗出自内心深处的欲望?我不知道,是性还是爱?我不清楚,很庆幸,她找到了自己一生值得守护的人,很开心吧!

但是,我怎么也开心不起来,因为,我的私心就是为什么不是我呢?因为,我还不够优秀,自己的路还有很长的路要走。自己的现在还是个孩子。

是的,我承认我真的很喜欢你,赵千秋。但是我喜欢的是以前的你,不是现在的你,现在的你,我似乎已经失去了兴趣,因为,你已经失去了自己的本心,你已经没有自己独立自主的能力,你现在在我的眼里,只是一具尸体,没有自己的灵魂,你脑海里面只有 做饭和洗衣服。很难想想你的世界里面还有什么呢?我不知道,我似乎现在也不像知道,是的,我以前表白过,但是不代表我不回变的,不会变的只是一颗对你好的心,是的,不乱你什么时候有困难找到我,我都会毫不犹豫的伸出援助之后。因为,可以说,没有你的话就没有我的今天。是的,以前的我,可能你也不是很了解我的。如果,不是你的话,我可能早就进去了。也说不一定,但是现在的我应该成长起来了。作为,你生命中的一个过客,自己的生活实在是太乏味了!是的,我的本性是懦弱的,因为很多时候,我不愿意面对的生活的中的困难,包括你,真的是不愿意面对!每一次去费县的时候,都会在你家门前默默的走过,自己的生活就是这样的。

默默的祝你幸福。也许是一个善意的谎言,也许就是真实的故事,很多事情,我并不知道对与错,我知道自己过得好才是最重要的,其他的都是扯淡。

Saturday, June 27, 2015

我的路才刚刚开始的!


 我的时光总是的真的不想。我喜欢的世界。

 就像是老舅说的,这个世界上不能老是依靠自己,自己的实力更能力都是有限的。所以,后面的路不是只是靠自己就可以走下去的,未来的路还有很长,所以现在,自己的技术和能力和人际圈子,还有很多的路要走呢!

 老舅,的路比我难走的多。自己经历的事情,现在才是刚刚开始呢,我的路有点漫长,我要走好慢慢的走好!

 不是跟我一般的近,是不会对我 推心置腹的这般对话!谈了很长的时间,是的,老舅经历的事情太多了。从黑龙江挖水管子,去山上栽树。很多时候的,都是我想都想不到的。在地下室住了两年,那个地方我真的是想都不敢想的,因为,之前张瑞鹏住的那个地方,我就知道,那个地方真的太潮了。生活,让我们真的密室了自己吗?

 我的未来不是梦想!

 我想走自己的路,但是这条路并不是那么好走的,因为很多时候,我们只知道自己明天做什么,但是并不清楚几年之后的规划,自己的具体的规划并没有做的那么详细。我的生活就是,这样,当一天和尚撞一天钟。这样的生活,我爱这样的生活。但是,有的时候,这样拖延症,实在是受不来哦饿了。有的时候,自己的规划是明白的自己的道路!














这样的世界? 你怎么看?


这个世界远远没有,你想象的那样美好。

就算你认识太多牛逼的人,但是你自己不够牛逼也是没有用的!因为,这个世界上没有傻瓜。人是相互,就跟力一样的。是的,我毕业了,我缺乏自信。老爸总是觉得,他应该为我做的更多,为我以后铺好路,但是,实际上,很多是事情,往往是我们在一厢情愿,很多人都有自己的想法,我们不能强迫别人,让别人的想法跟你一样的。那样,显然是不现实的,未来的路还有很长的。

现在的我擦刚刚的开始的起步吧! 人要知足,知足者常乐,但是我觉得自己的雄心太消极了。仿佛自己的雄心壮志已经被磨灭了。

我发现,自己真的很懒,很多时候根本就是不想去努力,并不是自己不可以努力。压力与动力是并发的,自己的路还有很长。现在的自己只不过是开始而已!

Internet is very much useful

 the internet is very useful!

 我找她,已经找了好几年了,QQ,人人,朋友网,博客,论坛等等。我都是过,今天,我终于找到她了。我的内心,真的很开心呢。寻找的辛苦真的肯困难,但是,最终的结果,我是很开心的,一切的都是源于 网络!


 很多时候,并不是我们想怎么样就会怎么样的!因为,你的想法,别人并不一定买账的。因为,每个人的想法都是不一样的。所以,我们需要学会换位思考。

 网络,上寻找室友一个前提的,因为巧妇难为无米之炊! 如果 她不玩网络,你有如何追踪到她的消息呢?是不是?其实,并不是所有的一切都是理所当然的,很多时候,都是一种上帝的眷顾。上帝也许真的存在呢?是吧?总是一颗感恩的心总是好的!

 昨天,她问我,找她做什么? 我的内心深处一梦。我真的不是到怎么回答。我的内心深处是说 我爱你。要不然我为什么会找你的信息?

 这就是人的欲望。总是想做一件事。我们的一生也正是如此,在不断的完成自己喜爱那个去做的每一件事情。因为这样自己的在不断的进步!

 今天,看马云的《我的人生哲学》 人们往往关注的是成功,而不是成长!

 自己的惰性!实在是,我的拖延症的真的苦恼啊!

-------------------------------------
 
 就算是,拿到了她的手机号,又能怎么样呢?人家根本就不接你的电话。
 屠龙之技,哈哈,我他妈也是醉了。这小妮子在想什么呀?看来我们的真的只是过客。不可能再有以前的那种种的情愫。自己的一厢情愿,换来的竟是这样的之句,觉得有点不甘心。回购拖来想象,很正常呀。我们每个人都有自己的正常的生活,我们不希望自己的生活被打扰到。所以,自己选择退避,或者,消极的退避。
 我们都是一样的,不喜欢跟自己的不喜欢的人聊天和交流!我们都是很任性的。这一点都没有错的呀!
因为我们的追求不同。她追求的,她想得到的,不一定就是现在你想的!

Thursday, June 25, 2015

创业还是打工仔? 真的很矛盾啊!

。。。。。。。

很庆幸,自己今天去面试了,本来真的不打算在面试了的,以为有一家 Offer就可以了,爱,人啊 就是便宜啊!

今天去面试的时候,感觉老大很不错,很喜欢,跟他在一块聊天的感觉很不错,似乎,通过他我似乎看到了十几年后的我,尽管我比较的年轻。是的,这一切都是相对而言的,并不是,凡是都是无绝对的。这个公司需要技术的大牛。现在的我,还只是一个初出茅庐的小子,还有很多的东西需要学习,现在只是一个开始而已!

很多时候,我们如果不逼迫自己的话,永远不知道自己几斤几两。有的时候,就是对自己太好了。是的,不思进取的时候,总是有的,自己的真的不愿意在这条路上走的更远,有的时候会扪心自问,我真的之这么多的钱吗?是的,有的时候,内心说实在的是很矛盾的。因为,自己老师不自信的,未来的路还有很长的,自己!

就像是老大说的,我现在才刚刚开始,如果,选择错了,就等于决定了自己的一生!

自己未来的路,自己思考!

跟别人干活,永远都是给别人干活,没有激情与活力。未来的路需要自己走下去,给自己干活才是真理,但是,我现在的技术还有人脉的圈子,还远远的达不到的。

就像是老大说的,现在不要小瞧,你身边的每一位人,因为,很有可能十年之后,就是你的老板,也说不一定的。有的时候,起点很重要的,但是选择之后的努力,会更加的重要的,因为,选择比努力更加的重要,有的时候努力不一定就会收货的,但是,你不理就一定不会有收获的,未来,是属于那些能够看到她的人,而不是,只在乎眼前利益的人。是的,很多时候,机会就是这样,稍纵即逝的,因为,我们也不知道自己的内心想要什么样的。

你是想卖一辈子的汽水,还是想跟我改变世界!

记住,自己积累的不仅仅是自己的技术,还有很多,人脉也很重要的,因为现在的这个时代,不在是美国的个人英雄主义时代了。因为,这个世界上,你应该明白,没有任何一个人,只靠自己就可以完成,一件事情,! 意见伟大事情,往往需要很多人的努力,不是说一两个人就可以的!

学会,跟自己的敌人做朋友! 这是一门很深的学问!

因为,从你的兄弟哪里,他们跟你粘在一起。支持你,鼓励你的人! 他们往往看不到我的缺点, 然而我的敌人,因为站在自己的对立面, 所以,他们更能看清出我的缺点,这样,会促进我的进步!



Wednesday, June 24, 2015

大学毕业季

我的大学毕业季,就这样子结束了。




毕业之后的我们。 毕业季的我是很疯狂的。真的很疯狂,很庆幸自己的毕业季没有闹出什么大的卵子还是比较平安的度过的。我很开心的,很多哥们一块疯狂,是的,有的进了,有的远了,这也是没有办法的,以为我们的原则和利益都是不一样的。也没有什么,一切都不是自己想的那个样子,这的很不愿意在付出那么多了,真的不愿意了。哈哈。

今天看到,我的梦中情人-蒋珊珊,发了一条说说,毕业季,马上就要结束了。我要回家了。是的,很多女孩子不想我一样,她们毕业之后很喜欢回到自己的家乡去创建自己美丽的家乡,因为父母很不放心她们在外面闯荡。这样,放在自己的什么身边,自己能够看到。是大多数父母的心愿。所以,父母开始给我们铺路子,很羡慕她们,毕业之后回到家里面。但是我的内心,并不愿意就这样放弃自己的(理想,具体我也说不上来。我也不知道是什么!)就是,自己的内心很不甘心,因为,我并不想她们一样,有一定的家庭背景,我需要靠自己的努力和汗水去打拼。

我想 乘风破浪会有是。

大丈夫, 壁立千仞 无欲则刚!

 Java 集合的类图

String、StringBuffer与StringBuilder之间区别

最近学习到StringBuffer,心中有好些疑问,搜索了一些关于String,StringBuffer,StringBuilder的东西,现在整理一下。
关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺点,到底什么时候该用谁呢?下面我们从以下几点说明一下
  1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String
  2.String <(StringBuffer,StringBuilder)的原因
    String:字符串常量
    StringBuffer:字符创变量
    StringBuilder:字符创变量
    从上面的名字可以看到,String是“字符创常量”,也就是不可改变的对象。对于这句话的理解你可能会产生这样一个疑问  ,比如这段代码:
1 String s = "abcd";2 = s+1;3 System.out.print(s);// result : abcd1

       我们明明就是改变了String型的变量s的,为什么说是没有改变呢? 其实这是一种欺骗,JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来    执行第二行代码,也就是说我们之前对象s并没有变化,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多底。
     而StringBuffer与StringBuilder就不一样了,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些而外的对象进行操作了,当然速度就快了。
  3.一个特殊的例子:
1 String str = “This is only a” + “ simple” + “ test”;
3 StringBuffer builder = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

  
    你会很惊讶的发现,生成str对象的速度简直太快了,而这个时候StringBuffer居然速度上根本一点都不占优势。其实这是JVM的一个把戏,实际上:
    String str = “This is only a” + “ simple” + “test”;
    其实就是:
    String str = “This is only a simple test”;
    所以不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,譬如:
    String str2 = “This is only a”;
    String str3 = “ simple”;
    String str4 = “ test”;
    String str1 = str2 +str3 + str4;
    这时候JVM会规规矩矩的按照原来的方式去做。
  4.StringBuilder与 StringBuffer
    StringBuilder:线程非安全的
    StringBuffer:线程安全的
    当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。

           对于三者使用的总结: 1.如果要操作少量的数据用 = String
                        2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
                        3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

          偶是初学者,只是总结了自己学习的东西,难免写的东西里有别人的,学习是记忆的过程,这些东西只是用来学习罢了,有些东西可能不对,希望各位给予指正。

Sunday, June 21, 2015

黑客领袖什么样?揭秘LulzSec领袖 曾攻击CIA

知名黑客组织LulzSec领袖赫克特·沙维尔·蒙赛格
LulzSec是更庞大的黑客组织Anonymous的分支
导语:福克斯新闻网站周二刊文称,知名黑客组织LulzSec的领袖赫克特·沙维尔·蒙赛格(Hector Xavier Monsegur)去年被美国联邦调查局逮捕。LulzSec此前攻击了美国中央情报局、福克斯、索尼和多家金融机构的网站。福克斯新闻网近期对抓捕蒙赛格的幕后情况进行了了解。
抓捕过程
2011年6月7日,这是美国全年中最热的一天之一,直到晚间气温仍然很高。两名联邦调查局探员在制服下身穿防弹背心,走进了位于纽约下东区的一处房屋。他们敲响了6楼一处公寓的房门,一名20多岁、身穿牛仔裤和白T恤的年轻人打开了房门。这名年轻人说:“我是赫克特。”
探员发现,与他们面对面的就是网名为“Sabu”的LulzSec领袖蒙赛格。联邦调查局已经花费了数个月的时间来追踪这名计算机天才,而直到此前数周才知道他的真实身份和所处位置。
LulzSec是更庞大的黑客组织Anonymous的分支,而蒙赛格则是该组织的领袖。此前几个月中,LulzSec攻击了美国中央情报局、福克斯和索尼等机构和公司的网站。根据媒体报道,攻击造成的损失达到数十亿美元。
从外表来看,这一不起眼的公寓不太可能是全球最知名黑客组织的中枢所在。不过28岁的蒙赛格本人也充满了这样的矛盾。蒙赛格是一名失业在家的计算机程序员、救济金领取者,以及两个孩子的法定监护人。蒙赛格没有上过大学,凭借自学成才成为一名黑客。尽管能力和聪明才智足以帮助蒙赛格找到一份不错的工作,但了解蒙赛格的人都说,他很懒惰、不思进取,并且对当前的生活状态很满意。
一名司法部门官员表示:“他极为聪明。聪明,但是懒惰。”懒惰或许是使蒙赛格陷入目前处境的最主要原因。
行踪泄露
在进行黑客活动时,蒙赛格总是非常谨慎,通过代理服务器隐藏自己的IP地址。不过蒙赛格也曾出现过一次疏忽。当时他使用自己的真实IP地址登录了一个聊天室,而就是这次疏忽帮助了联邦调查局的抓捕。
联邦调查局探员随后观察了这一IP地址在几周内的活动,并确定IP地址的使用者就是LulzSec的领袖“Sabu”。6月7日晚间,联邦调查局接到报告称,有人在网上发布了“Sabu”的真实姓名和住址。执法部门担心,“Sabu”在看到这则信息之后将会离开住所并销毁黑客活动的证据,因此他们必须立即行动。
联邦调查局此前已经获得了“Sabu”的Facebook帐户,发现他曾向其他黑客出售窃取的信用卡号码。因此,联邦调查局已有足够证据以重度身份信息窃取的罪名起诉他,并使他面临至少两年的监禁。不过对调查者来说,“Sabu”如果愿意合作,那么能带来更有价值的信息。
根据一名目击者的说法,在房门打开之后,蒙赛格表示:“这不是我,你们找错了人。我没有计算机。”然而探员看到,在蒙赛格的身后,他的网线连接在DSL调制解调器上,而绿灯仍在闪烁。
探员以先礼后兵的方式使蒙赛格就范,并搜查了他的房间。蒙赛格最终放弃了狡辩,将所有工具都交给了执法部门。其中一名探员回忆称:“这是由于他的孩子。他愿意为孩子做一切。他不希望进监狱,而使孩子无人照管。这就是我们说服他的方式。”
蒙赛格以重度身份信息窃取的罪名被起诉,随后被保释。8月15日,他对于一系列与黑客活动相关的指控表示认罪,并同意与联邦调查局合作。知情人士称,蒙赛格继续与他的孩子生活在公寓里,与他们一起生活的还包括他的5个兄弟和1个姐妹。
成长经历
自那时以来,蒙赛格开始为政府部门工作,而这一雇主正是他此前试图攻击的对象。根据知情者的说法,蒙赛格的网名“Sabu”来自纽约斯塔顿岛的一名职业摔跤手SabutheElephantBoy。这名摔跤手曾声称自己是沙特阿拉伯裔,从而引起了当地群众的不满。SabutheElephantBoy活跃于80年代和90年代的独立职业摔跤比赛中,并有一定的声誉。
了解蒙赛格的人表示,蒙赛格反对政府、反对资本主义的态度是促使他进行黑客活动的主要原因。他的人际交往技巧、技术能力、在街头的声望,以及所进行的黑客活动使他很快在黑客圈中崛起。蒙赛格的活动很多出于政治目的,他曾经因反对亚利桑那州的移民法而公布了该州司法部门工作人员的个人信息。
Anonymous和LulzSec成员自称为黑客活动家,他们有着明确的日程和活动主题。此前,蒙赛格曾供职于一家名为Limewire的公司,该公司开发P2P分享软件,帮助用户“解放”音乐。
这样的文件分享软件很明显存在侵权行为。而在Napster之后,一些新的文件分享网络也被迫关闭。Limewire最终也被关闭,并遭到美国唱片业协会RIAA的起诉,被索赔1.05亿美元。蒙赛格随后失去了工作,并一直处于失业状态。
不过知情者表示,考虑到他出色的能力,蒙赛格本可以再找到很好的工作。一名司法部门官员表示:“如果加入大公司的IT安全部门,‘Sabu’可以赚到数百万美元。不过,他现在已经穷困潦倒,依靠公共援助和求助于朋友为生。他还可能在监狱中度过一生。这确实非常悲惨。”'


感悟:
一次失误,结束了你的一生。所以,注意细节,细节决定成败。因为,只有一次没有使用代理就把自己的IP地址暴露了。而这,直接导致了他的之后的经历!

全球十大著名黑客盘点     致敬

日前,国外媒体刊登文章,对著名的黑客进行了盘点,而在这一榜单中,苹果联合创始人乔布斯·史蒂夫(Steve Jobs)和史蒂夫·沃兹尼亚克(Steve Wozniak)也榜上有名。黑客们并非总是破坏或者盗取信息的坏蛋,一些出名的黑客实确实最终锒铛入狱。但他们中的许多人已经成为了拥有众多成果的守法公民,成立了自己的公司、成为亿万富翁,或者是出版了销售书。
随着越来越多计算机攻击事件成为头版头条,以下为对一些出名黑客人物的回顾,他们中的许多人,都曾经发现他们有时会游离于正义与邪恶之间。
凯文·米特尼克(Kevin Mitnick)

全球十大著名黑客盘点 乔布斯榜上有名
米特尼克曾经是美国最想要抓到的犯罪分子,他曾经攻入五角大楼和美国数字设备公司(Digital Equipment Corp)等机构的计算机网络。
米特尼克多次因黑客攻击而被捕入狱,这也使他成为了业界名人。他在内华达州开办了米特尼克安全顾问公司(Mitnick Security Consulting),他还是一位作家。他的最新作品《线中幽灵》(Ghost in the Wires)记录了他最为著名的黑客攻击事件,而小说《骇客追缉令》(Takedown)就是讲述他的故事,《骇客追缉令》描述了在90年代中叶,对米特尼克的抓捕过程。自从米特尼克获释出狱以来,他仍旧是是公众关注的焦点,频繁受邀演讲和进行签名售书。
乔治·霍茨(George Hotz)
全球十大著名黑客盘点 乔布斯榜上有名

霍茨是名年仅22岁的黑客,他因将苹果iPhone手机越狱(jailbreaking),和破解索尼PlayStation 3,而名声大振,而对PlayStation 3的破解,最终也使得霍茨与索尼对薄公堂。
索尼对霍茨提起诉讼,双方最终达成和解,索尼禁止霍茨破解索其产品。而黑客组织Anonymous则继承了霍茨的事业,针对索尼发起了报复性攻击。霍茨此后被社交网站Facebook招致麾下。
艾德里安·拉莫(Adrian Lamo)
全球十大著名黑客盘点 乔布斯榜上有名
艾德里安因入侵《纽约时报》(New York Times)的计算机网络,而在2003年被捕,他在一系列Op-Ed投稿人中添加自己的名字,并使用一个LexisNexis账号进行搜索。他被判在家监禁。
艾德里安在2010年重新回到公众的视线之中,艾德里安当时向美国政府报料称,前美军陆军情报分析员布拉德利·曼宁(Bradley Manning)称,他已经将政府机密外交文件泄露给维基解密。曼宁被指控非法传递信息,而艾德里安则被一些业内同行视为是叛徒,这也导致了他在互联网和黑客大会上受到指责。
罗伯特·塔潘-莫里斯(Robert Tappan Morris)
全球十大著名黑客盘点 乔布斯榜上有名
罗伯特在1988年时就已经臭名昭著,他当时是康奈尔大学(Cornell University)的研究生,他在互联网上发布了首个被广泛传播的蠕虫病毒,造成数千台电脑崩溃。
罗伯特是美国国家计算机安全中心(隶属于美国国家安全局NSA)首席科学家的儿子。罗伯特称,该款程序是一项研究实验,而该实验失去了控制。他成为首位遭到反黑客行为法(anti-hacking law)指控的黑客,该法案认定入侵联邦计算机系统为非法。罗伯特最终被罚1万美元,并被命令从事400个小时的社区服务。一些安全专家认为这一判罚过高,这是因为考虑到这种类型的互联网攻击,现在几乎每天都在发生。
罗伯特现在是麻省理工学院(Massachusetts Institute of Technology)的计算机科学教授。
马克斯·巴特尔(Max Butler)
全球十大著名黑客盘点 乔布斯榜上有名
巴特尔曾是FBI的线人,他运营一个盗用信用卡的网站CardersMarket.com,该网站也是互联网上一个最大的商业犯罪网站,该网站拥有数千名用户,巴特尔在位于旧金山的家中,运营该网站。
使用被盗信用卡在零售店消费被抓获等一系列的失误,使得该网站被发现,巴特尔被逮捕,并被判入狱。由于窃取了200万张信用卡的信息,欺诈损失达8600万美元,巴特尔最终被判入狱13年。
迈克尔·林恩(Michael Lynn)
全球十大著名黑客盘点 乔布斯榜上有名
迈克尔在2005年名声鹤起,当时思科不遗余力的想要阻止迈克尔关于软件漏洞的演示,该软件漏洞能允许黑客攻击并控制思科路由器。思科威胁提起诉讼,并命令员工销毁了2000张含有演示文档的CD。
迈克尔从网络安全系统公司(Internet Security Systems)离职,迈克尔称,该公司对他施压,要求他停止进行演示。迈克尔最终进行了演示,成为一名黑客英雄。迈克尔现在为思科的竞争对手瞻博网络 (Juniper Networks)工作,担任高级工程师一职。
艾伯特·冈萨雷斯(Albert Gonzalez)
全球十大著名黑客盘点 乔布斯榜上有名
冈萨雷斯曾是美国特勤局(U.S. Secret Service)的线人,由于被美国当局指控从事美国有史以来规模最大的信用卡盗窃案,因此他被判入狱20年。
冈萨雷斯被证实与国际犯罪集团一起,从美国零售商TJX Cos、OfficeMax和BJ's Wholesale Club等处,盗取了4000万张信用卡信息。检方指出,他同意放弃的逾100万美元现金,被发现埋藏在他父母后院的一个桶里。
凯文·波尔森(Kevin Poulsen)
全球十大著名黑客盘点 乔布斯榜上有名
波尔森是被证实有罪的电脑黑客,他将自己转型成为一位顶级的、安全领域的新闻记者。他是《Kingpin》一书的作者。
波尔森擅长于攻击电话网络,他曾经攻击了洛杉矶KIIS FM电台的电话线路,以便成为“周五赢辆保时捷”(Win a Porsche By Friday)节目获胜呼入者。波尔森被判入狱5年。
史蒂夫·沃兹尼亚克(Steve Wozniak)和乔布斯·史蒂夫(Steve Jobs)
全球十大著名黑客盘点 乔布斯榜上有名
苹果联合创始人早期曾是电话飞客(phone phreakers),他们利用电话网络中的漏洞免费拨打电话。被称为“奥拉夫·图巴克”(Oaf Tobark)的乔布斯和被叫做“伯克利蓝”(Berkeley Blue)沃兹尼亚,他们出售盗用电话线路的“蓝色盒子”(blue boxes),一直到他们在硅谷一家比萨店的停车场遭遇到持枪抢劫。
乔布斯在2011年10月去世,他曾表示,黑客经历是创建苹果的必然先导。沃兹尼亚克现在在总部位于盐湖城的计算机存储厂商Fusion-io,担任首席科学家。

全球的最火的 黑客

全球最牛黑客巴纳拜·杰克

How to set wifi in ubuntu 14.10 Thinkpad E431

参考网址:https://help.ubuntu.com/community/WifiDocs/Driver/bcm43xx?action=show&redirect=BroadcomSTA%28Wireless%29


command:


Open a Terminal and install the bcmwl-kernel-source package:
sudo apt-get update
sudo apt-get --reinstall install bcmwl-kernel-source

Note: If you see the message "Module build for the currently running kernel was skipped since the kernel source for this kernel does not seem to be installed" then you are missing the appropriate generic linux-header package(s).

Saturday, June 20, 2015

感谢网络

g

人生总是聚少离多?

 是的,我们真的在乎的自己在乎的东西,而不是别人。
 他们不会像: 你对他们那样的对你的奥。

 是的,今天早上的猜想是对的,但是呢,心里面还是有点不爽啊。有的时候,也许一家庭真的需要一个女孩子来维持一种平衡。但是,我跟他都是很僵的人。不愿意将就。

 一切,都走了,就只剩下了我们。是的,很庆幸还有人能和自己一起度过!

现在,就是孤独的的,很多时候,不是别人的想法都和你一样的奥。嘿嘿,未来的路就在自己的脚下。我很喜欢, 露在脚下,就看你自己能走多远了!

how to isntall putty in ubuntu?

you just input in command:

sudo apt-get input putty

人生就像是一场梦!

我现在也不知道该怎么讲,是的大宝是真的很不错。但是,我是真心的不愿意,现在的嫂子过来的,傻逼一个。

很多事情,不是想自己想象的那样。真的,很有可能,大宝会因为嫂子而搬出去,真是认知常情。这可能也是他的意思。是的,大宝真的很为难。如果,作为一个男人,连自己的老婆都照顾不好,有怎么看以后呢?嫂子,可能以为,我们很愿意跟她在一起呢?其实,并不是,她真心的很小心眼。很多事情,并不是她想的那样,但是,老师把人忘那方面想。很多时候我也是醉了,真的很无奈。  女人 我是搞不懂的。

人生总是聚少离多,很多事情我也是没有办法,所以,我需要做的就是珍惜眼前的一切,可能几天之后就再也找不到了。我的生活不可能总是想自己想的那样美好的。如果,嫂子真的住进来。我也不能说什么呀。但是以后的事 就多了!

《创京东》feeling

 I don't like this, It just the news of liu dong qiang . There is nothind in it ,that you can learn . So  i don't buy like this book .

是的,我一直觉得读书是自己的一笔财富。现在,发现,需要添加一个定语。是一流的书,有的书买来读,简直了,简直就是在浪费自己的青春时间。以后类似与 创京东还有扎克博格类似的书,看到书名就直接放弃。我操了。不仅 费钱 还浪费我的时间。

有的书,可以用一辈子的时间来读。有的书,感觉花一分钟在上面就是在浪费自己的时间。

总的来讲: 我知道了刘强东 这一路走在是很不容易的。但是书中,一直在吹嘘 刘强东是如如何牛逼。京东的战略布局是如何如何的屌。就是一部 新闻的剪辑。

浪费钱是小事,但是浪费自己的青春时间在如此垃圾的书上就是我的不对了!

Thursday, June 18, 2015

Android 多屏幕适配

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992
Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因、重要概念、解决方案及最佳实践,我相信如果你能认真的学习本文,对于Android的屏幕适配,你将有所收获!

Android屏幕适配出现的原因

在我们学习如何进行屏幕适配之前,我们需要先了解下为什么Android需要进行屏幕适配。
由于Android系统的开放性,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,修改成他们想要的样子。
但是这种“碎片化”到底到达什么程度呢?
在2012年,OpenSignalMaps(以下简称OSM)发布了第一份Android碎片化报告,统计数据表明,
  • 2012年,支持Android的设备共有3997种。
  • 2013年,支持Android的设备共有11868种。
  • 2014年,支持Android的设备共有18796种。
下面这张图片所显示的内容足以充分说明当今Android系统碎片化问题的严重性,因为该图片中的每一个矩形都代表着一种Android设备。
而随着支持Android系统的设备(手机、平板、电视、手表)的增多,设备碎片化、品牌碎片化、系统碎片化、传感器碎片化和屏幕碎片化的程度也在不断地加深。而我们今天要探讨的,则是对我们开发影响比较大的——屏幕的碎片化。
下面这张图是Android屏幕尺寸的示意图,在这张图里面,蓝色矩形的大小代表不同尺寸,颜色深浅则代表所占百分比的大小。
而与之相对应的,则是下面这张图。这张图显示了IOS设备所需要进行适配的屏幕尺寸和占比。
当然,这张图片只是4,4s,5,5c,5s和平板的尺寸,现在还应该加上新推出的iphone6和plus,但是和Android的屏幕碎片化程度相比而言,还是差的太远。
详细的统计数据请到这里查看
现在你应该很清楚为什么要对Android的屏幕进行适配了吧?屏幕尺寸这么多,为了让我们开发的程序能够比较美观的显示在不同尺寸、分辨率、像素密度(这些概念我会在下面详细讲解)的设备上,那就要在开发的过程中进行处理,至于如何去进行处理,这就是我们今天的主题了。
但是在开始进入主题之前,我们再来探讨一件事情,那就是Android设备的屏幕尺寸,从几寸的智能手机,到10寸的平板电脑,再到几十寸的数字电视,我们应该适配哪些设备呢?
其实这个问题不应该这么考虑,因为对于具有相同像素密度的设备来说,像素越高,尺寸就越大,所以我们可以换个思路,将问题从单纯的尺寸大小转换到像素大小和像素密度的角度来。
下图是2014年初,友盟统计的占比5%以上的6个主流分辨率,可以看出,占比最高的是480*800,320*480的设备竟然也占据了很大比例,但是和半年前的数据相比较,中低分辨率(320*480、480*800)的比例在减少,而中高分辨率的比例则在不断地增加。虽然每个分辨率所占的比例在变化,但是总的趋势没变,还是这六种,只是分辨率在不断地提高。
所以说,我们只要尽量适配这几种分辨率,就可以在大部分的手机上正常运行了。
当然了,这只是手机的适配,对于平板设备(电视也可以看做是平板),我们还需要一些其他的处理。
好了,到目前为止,我们已经弄清楚了Android开发为什么要进行适配,以及我们应该适配哪些对象,接下来,终于进入我们的正题了!
首先,我们先要学习几个重要的概念。

重要概念

什么是屏幕尺寸、屏幕分辨率、屏幕像素密度? 
什么是dp、dip、dpi、sp、px?他们之间的关系是什么? 
什么是mdpi、hdpi、xdpi、xxdpi?如何计算和区分?
在下面的内容中我们将介绍这些概念。

屏幕尺寸

屏幕尺寸指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米
比如常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等

屏幕分辨率

屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以纵向像素*横向像素,如1960*1080。

屏幕像素密度

屏幕像素密度是指每英寸上的像素点数,单位是dpi,即“dot per inch”的缩写。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

dp、dip、dpi、sp、px

px我们应该是比较熟悉的,前面的分辨率就是用的像素为单位,大多数情况下,比如UI设计、Android原生API都会以px作为统一的计量单位,像是获取屏幕宽高等。
dip和dp是一个意思,都是Density Independent Pixels的缩写,即密度无关像素,上面我们说过,dpi是屏幕像素密度,假如一英寸里面有160个像素,这个屏幕的像素密度就是160dpi,那么在这种情况下,dp和px如何换算呢?在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1dip=2px,以此类推。
假如同样都是画一条320px的线,在480*800分辨率手机上显示为2/3屏幕宽度,在320*480的手机上则占满了全屏,如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一般的长度。这也是为什么在Android开发中,写布局的时候要尽量使用dp而不是px的原因。
而sp,即scale-independent pixels,与dp类似,但是可以根据文字大小首选项进行放缩,是设置字体大小的御用单位。

mdpi、hdpi、xdpi、xxdpi

其实之前还有个ldpi,但是随着移动设备配置的不断升级,这个像素密度的设备已经很罕见了,所在现在适配时不需考虑。
mdpi、hdpi、xdpi、xxdpi用来修饰Android中的drawable文件夹及values文件夹,用来区分不同像素密度下的图片和dimen值。
那么如何区分呢?Google官方指定按照下列标准进行区分:
名称像素密度范围
mdpi120dpi~160dpi
hdpi160dpi~240dpi
xhdpi240dpi~320dpi
xxhdpi320dpi~480dpi
xxxhdpi480dpi~640dpi
在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面。下面以图标设计为例进行介绍。
在设计图标时,对于五种主流的像素密度(MDPI、HDPI、XHDPI、XXHDPI 和 XXXHDPI)应按照 2:3:4:6:8 的比例进行缩放。例如,一个启动图标的尺寸为48x48 dp,这表示在 MDPI 的屏幕上其实际尺寸应为 48x48 px,在 HDPI 的屏幕上其实际大小是 MDPI 的 1.5 倍 (72x72 px),在 XDPI 的屏幕上其实际大小是 MDPI 的 2 倍 (96x96 px),依此类推。
虽然 Android 也支持低像素密度 (LDPI) 的屏幕,但无需为此费神,系统会自动将 HDPI 尺寸的图标缩小到 1/2 进行匹配。
下图为图标的各个屏幕密度的对应尺寸
屏幕密度图标尺寸
mdpi48x48px
hdpi72x72px
xhdpi96x96px
xxhdpi144x144px
xxxhdpi192x192px

解决方案

支持各种屏幕尺寸

使用wrap_content、match_parent、weight

要确保布局的灵活性并适应各种尺寸的屏幕,应使用 “wrap_content” 和 “match_parent” 控制某些视图组件的宽度和高度。
使用 “wrap_content”,系统就会将视图的宽度或高度设置成所需的最小尺寸以适应视图中的内容,而 “match_parent”(在低于 API 级别 8 的级别中称为 “fill_parent”)则会展开组件以匹配其父视图的尺寸。
如果使用 “wrap_content” 和 “match_parent” 尺寸值而不是硬编码的尺寸,视图就会相应地仅使用自身所需的空间或展开以填满可用空间。此方法可让布局正确适应各种屏幕尺寸和屏幕方向。
下面是一段示例代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout android:layout_width="match_parent"
                  android:id="@+id/linearLayout1"  
                  android:gravity="center"
                  android:layout_height="50dp">
        <ImageView android:id="@+id/imageView1"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
                   android:src="@drawable/logo"
                   android:paddingRight="30dp"
                   android:layout_gravity="left"
                   android:layout_weight="0" />
        <View android:layout_height="wrap_content"
              android:id="@+id/view1"
              android:layout_width="wrap_content"
              android:layout_weight="1" />
        <Button android:id="@+id/categorybutton"
                android:background="@drawable/button_bg"
                android:layout_height="match_parent"
                android:layout_weight="0"
                android:layout_width="120dp"
                style="@style/CategoryButtonStyle"/>
    </LinearLayout>

    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
下图是在横纵屏切换的时候的显示效果,我们可以看到这样可以很好的适配屏幕尺寸的变化。
weight是线性布局的一个独特的属性,我们可以使用这个属性来按照比例对界面进行分配,完成一些特殊的需求。
但是,我们对于这个属性的计算应该如何理解呢?
首先看下面的例子,我们在布局中这样设置我们的界面
我们在布局里面设置为线性布局,横向排列,然后放置两个宽度为0dp的按钮,分别设置weight为1和2,在效果图中,我们可以看到两个按钮按照1:2的宽度比例正常排列了,这也是我们经常使用到的场景,这是时候很好理解,Button1的宽度就是1/(1+2) = 1/3,Button2的宽度则是2/(1+2) = 2/3,我们可以很清楚的明白这种情景下的占比如何计算。
但是假如我们的宽度不是0dp(wrap_content和0dp的效果相同),则是match_parent呢?
下面是设置为match_parent的效果
我们可以看到,在这种情况下,占比和上面正好相反,这是怎么回事呢?说到这里,我们就不得不提一下weight的计算方法了。
android:layout_weight的真实含义是:如果View设置了该属性并且有效,那么该 View的宽度等于原有宽度(android:layout_width)加上剩余空间的占比。
从这个角度我们来解释一下上面的现象。在上面的代码中,我们设置每个Button的宽度都是match_parent,假设屏幕宽度为L,那么每个Button的宽度也应该都为L,剩余宽度就等于L-(L+L)= -L。
Button1的weight=1,剩余宽度占比为1/(1+2)= 1/3,所以最终宽度为L+1/3*(-L)=2/3L,Button2的计算类似,最终宽度为L+2/3(-L)=1/3L。
这是在水平方向上的,那么在垂直方向上也是这样吗?
下面是测试代码和效果
如果是垂直方向,那么我们应该改变的是layout_height的属性,下面是0dp的显示效果
下面是match_parent的显示效果,结论和水平是完全一样的
虽然说我们演示了match_parent的显示效果,并说明了原因,但是在真正用的时候,我们都是设置某一个属性为0dp,然后按照权重计算所占百分比。

使用相对布局,禁用绝对布局

在开发中,我们大部分时候使用的都是线性布局、相对布局和帧布局,绝对布局由于适配性极差,所以极少使用。
由于各种布局的特点不一样,所以不能说哪个布局好用,到底应该使用什么布局只能根据实际需求来确定。我们可以使用 LinearLayout 的嵌套实例并结合 “wrap_content” 和 “match_parent”,以便构建相当复杂的布局。不过,我们无法通过 LinearLayout 精确控制子视图的特殊关系;系统会将 LinearLayout 中的视图直接并排列出。
如果我们需要将子视图排列出各种效果而不是一条直线,通常更合适的解决方法是使用 RelativeLayout,这样就可以根据各组件之间的特殊关系指定布局了。例如,我们可以将某个子视图对齐到屏幕左侧,同时将另一个视图对齐到屏幕右侧。
下面的代码以官方Demo为例说明。
<?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">
    <TextView
        android:id="@+id/label"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Type here:"/>
    <EditText
        android:id="@+id/entry"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/label"/>
    <Button
        android:id="@+id/ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/entry"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="10dp"
        android:text="OK" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/ok"
        android:layout_alignTop="@id/ok"
        android:text="Cancel" />
</RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
在上面的代码中我们使用了相对布局,并且使用alignXXX等属性指定了子控件的位置,下面是这种布局方式在应对屏幕变化时的表现
在小尺寸屏幕的显示
在平板的大尺寸上的显示效果
虽然控件的大小由于屏幕尺寸的增加而发生了改变,但是我们可以看到,由于使用了相对布局,所以控件之前的位置关系并没有发生什么变化,这说明我们的适配成功了。

使用限定符

使用尺寸限定符

上面所提到的灵活布局或者是相对布局,可以为我们带来的优势就只有这么多了。虽然这些布局可以拉伸组件内外的空间以适应各种屏幕,但它们不一定能为每种屏幕都提供最佳的用户体验。因此,我们的应用不仅仅只实施灵活布局,还应该应针对各种屏幕配置提供一些备用布局。
如何做到这一点呢?我们可以通过使用配置限定符,在运行时根据当前的设备配置自动选择合适的资源了,例如根据各种屏幕尺寸选择不同的布局。
很多应用会在较大的屏幕上实施“双面板”模式,即在一个面板上显示项目列表,而在另一面板上显示对应内容。平板电脑和电视的屏幕已经大到可以同时容纳这两个面板了,但手机屏幕就需要分别显示。因此,我们可以使用以下文件以便实施这些布局:
res/layout/main.xml,单面板(默认)布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
res/layout-large/main.xml,双面板布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
请注意第二种布局名称目录中的 large 限定符。系统会在属于较大屏幕(例如 7 英寸或更大的平板电脑)的设备上选择此布局。系统会在较小的屏幕上选择其他布局(无限定符)。

使用最小宽度限定符

在版本低于 3.2 的 Android 设备上,开发人员遇到的问题之一是“较大”屏幕的尺寸范围,该问题会影响戴尔 Streak、早期的 Galaxy Tab 以及大部分 7 英寸平板电脑。即使这些设备的屏幕属于“较大”的尺寸,但很多应用可能会针对此类别中的各种设备(例如 5 英寸和 7 英寸的设备)显示不同的布局。这就是 Android 3.2 版在引入其他限定符的同时引入“最小宽度”限定符的原因。
最小宽度限定符可让您通过指定某个最小宽度(以 dp 为单位)来定位屏幕。例如,标准 7 英寸平板电脑的最小宽度为 600 dp,因此如果您要在此类屏幕上的用户界面中使用双面板(但在较小的屏幕上只显示列表),您可以使用上文中所述的单面板和双面板这两种布局,但您应使用 sw600dp 指明双面板布局仅适用于最小宽度为 600 dp 的屏幕,而不是使用 large 尺寸限定符。
res/layout/main.xml,单面板(默认)布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
res/layout-sw600dp/main.xml,双面板布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
也就是说,对于最小宽度大于等于 600 dp 的设备,系统会选择 layout-sw600dp/main.xml(双面板)布局,否则系统就会选择 layout/main.xml(单面板)布局。
但 Android 版本低于 3.2 的设备不支持此技术,原因是这些设备无法将 sw600dp 识别为尺寸限定符,因此我们仍需使用 large 限定符。这样一来,就会有一个名称为 res/layout-large/main.xml 的文件(与 res/layout-sw600dp/main.xml 一样)。但是没有太大关系,我们将马上学习如何避免此类布局文件出现的重复。

使用布局别名

最小宽度限定符仅适用于 Android 3.2 及更高版本。因此,如果我们仍需使用与较低版本兼容的概括尺寸范围(小、正常、大和特大)。例如,如果要将用户界面设计成在手机上显示单面板,但在 7 英寸平板电脑、电视和其他较大的设备上显示多面板,那么我们就需要提供以下文件:
  • res/layout/main.xml: 单面板布局
  • res/layout-large: 多面板布局
  • res/layout-sw600dp: 多面板布局
后两个文件是相同的,因为其中一个用于和 Android 3.2 设备匹配,而另一个则是为使用较低版本 Android 的平板电脑和电视准备的。
要避免平板电脑和电视的文件出现重复(以及由此带来的维护问题),您可以使用别名文件。例如,您可以定义以下布局:
  • res/layout/main.xml,单面板布局
  • res/layout/main_twopanes.xml,双面板布局
然后添加这两个文件:
res/values-large/layout.xml:
<resources>
    <item name="main" type="layout">@layout/main_twopanes</item>
</resources>
  • 1
  • 2
  • 3
res/values-sw600dp/layout.xml:
<resources>
    <item name="main" type="layout">@layout/main_twopanes</item>
</resources>
  • 1
  • 2
  • 3
后两个文件的内容相同,但它们并未实际定义布局。它们只是将 main 设置成了 main_twopanes 的别名。由于这些文件包含 large 和 sw600dp 选择器,因此无论 Android 版本如何,系统都会将这些文件应用到平板电脑和电视上(版本低于 3.2 的平板电脑和电视会匹配 large,版本高于 3.2 的平板电脑和电视则会匹配 sw600dp)。

使用屏幕方向限定符

某些布局会同时支持横向模式和纵向模式,但我们可以通过调整优化其中大部分布局的效果。在新闻阅读器示例应用中,每种屏幕尺寸和屏幕方向下的布局行为方式如下所示:
  • 小屏幕,纵向:单面板,带徽标
  • 小屏幕,横向:单面板,带徽标
  • 7 英寸平板电脑,纵向:单面板,带操作栏
  • 7 英寸平板电脑,横向:双面板,宽,带操作栏
  • 10 英寸平板电脑,纵向:双面板,窄,带操作栏
  • 10 英寸平板电脑,横向:双面板,宽,带操作栏
  • 电视,横向:双面板,宽,带操作栏
因此,这些布局中的每一种都定义在了 res/layout/ 目录下的某个 XML 文件中。为了继续将每个布局分配给各种屏幕配置,该应用会使用布局别名将两者相匹配:
res/layout/onepane.xml:(单面板)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
res/layout/onepane_with_bar.xml:(单面板带操作栏)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout android:layout_width="match_parent"
                  android:id="@+id/linearLayout1"  
                  android:gravity="center"
                  android:layout_height="50dp">
        <ImageView android:id="@+id/imageView1"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
                   android:src="@drawable/logo"
                   android:paddingRight="30dp"
                   android:layout_gravity="left"
                   android:layout_weight="0" />
        <View android:layout_height="wrap_content"
              android:id="@+id/view1"
              android:layout_width="wrap_content"
              android:layout_weight="1" />
        <Button android:id="@+id/categorybutton"
                android:background="@drawable/button_bg"
                android:layout_height="match_parent"
                android:layout_weight="0"
                android:layout_width="120dp"
                style="@style/CategoryButtonStyle"/>
    </LinearLayout>

    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
res/layout/twopanes.xml:(双面板,宽布局)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
res/layout/twopanes_narrow.xml:(双面板,窄布局)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="200dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
既然我们已定义了所有可能的布局,那就只需使用配置限定符将正确的布局映射到各种配置即可。
现在只需使用布局别名技术即可做到这一点:
res/values/layouts.xml:
<resources>
    <item name="main_layout" type="layout">@layout/onepane_with_bar</item>
    <bool name="has_two_panes">false</bool>
</resources>
  • 1
  • 2
  • 3
  • 4
res/values-sw600dp-land/layouts.xml:
<resources>
    <item name="main_layout" type="layout">@layout/twopanes</item>
    <bool name="has_two_panes">true</bool>
</resources>
  • 1
  • 2
  • 3
  • 4
res/values-sw600dp-port/layouts.xml:
<resources>
    <item name="main_layout" type="layout">@layout/onepane</item>
    <bool name="has_two_panes">false</bool>
</resources>
  • 1
  • 2
  • 3
  • 4
res/values-large-land/layouts.xml:
<resources>
    <item name="main_layout" type="layout">@layout/twopanes</item>
    <bool name="has_two_panes">true</bool>
</resources>
  • 1
  • 2
  • 3
  • 4
res/values-large-port/layouts.xml:
<resources>
    <item name="main_layout" type="layout">@layout/twopanes_narrow</item>
    <bool name="has_two_panes">true</bool>
</resources>
  • 1
  • 2
  • 3
  • 4

使用自动拉伸位图

支持各种屏幕尺寸通常意味着您的图片资源还必须能适应各种尺寸。例如,无论要应用到什么形状的按钮上,按钮背景都必须能适应。
如果在可以更改尺寸的组件上使用了简单的图片,您很快就会发现显示效果多少有些不太理想,因为系统会在运行时平均地拉伸或收缩您的图片。解决方法为使用自动拉伸位图,这是一种格式特殊的 PNG 文件,其中会指明可以拉伸以及不可以拉伸的区域。
.9的制作,实际上就是在原图片上添加1px的边界,然后按照我们的需求,把对应的位置设置成黑色线,系统就会根据我们的实际需求进行拉伸。
下图是对.9图的四边的含义的解释,左上边代表拉伸区域,右下边代表padding box,就是间隔区域,在下面,我们给出一个例子,方便大家理解。
先看下面两张图,我们理解一下这四条线的含义。
上图和下图的区别,就在于右下边的黑线不一样,具体的效果的区别,看右边的效果图。上图效果图中深蓝色的区域,代表内容区域,我们可以看到是在正中央的,这是因为我们在右下边的是两个点,这两个点距离上下左右四个方向的距离就是padding的距离,所以深蓝色内容区域在图片正中央,我们再看下图,由于右下边的黑线是图片长度,所以就没有padding,从效果图上的表现就是深蓝色区域和图片一样大,因此,我们可以利用右下边来控制内容与背景图边缘的padding。
如果你还不明白,那么我们看下面的效果图,我们分别以图一和图二作为背景图,下面是效果图。
我们可以看到,使用wrap_content属性设置长宽,图一比图二的效果大一圈,这是为什么呢?还记得我上面说的padding吗?
这就是padding的效果提现,怎么证明呢?我们再看下面一张图,给图一添加padding=0,这样背景图设置的padding效果就没了,是不是两个一样大了?
ok,我想你应该明白右下边的黑线的含义了,下面我们再看一下左上边的效果。
下面我们只设置了左上边线,效果图如下
上面的线没有包住图标,下面的线正好包住了图标,从右边的效果图应该可以看出差别,黑线所在的区域就是拉伸区域,上图黑线所在的全是纯色,所以图标不变形,下面的拉伸区域包裹了图标,所以在拉伸的时候就会对图标进行拉伸,但是这样就会导致图标变形。注意到下面红线区域了嘛?这是系统提示我们的,因为这样拉伸,不符合要求,所以会提示一下。

支持各种屏幕密度

使用非密度制约像素

由于各种屏幕的像素密度都有所不同,因此相同数量的像素在不同设备上的实际大小也有所差异,这样使用像素定义布局尺寸就会产生问题。因此,请务必使用 dp 或 sp 单位指定尺寸。dp 是一种非密度制约像素,其尺寸与 160 dpi 像素的实际尺寸相同。sp 也是一种基本单位,但它可根据用户的偏好文字大小进行调整(即尺度独立性像素),因此我们应将该测量单位用于定义文字大小。
例如,请使用 dp(而非 px)指定两个视图间的间距:
<Button android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/clickme"
    android:layout_marginTop="20dp" />
  • 1
  • 2
  • 3
  • 4
请务必使用 sp 指定文字大小:
<TextView android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp" />
  • 1
  • 2
  • 3
除了介绍这些最基础的知识之外,我们下面再来讨论一下另外一个问题。
经过上面的介绍,我们都清楚,为了能够规避不同像素密度的陷阱,Google推荐使用dp来代替px作为控件长度的度量单位,但是我们来看下面的一个场景。
假如我们以Nexus5作为书写代码时查看效果的测试机型,Nexus5的总宽度为360dp,我们现在需要在水平方向上放置两个按钮,一个是150dp左对齐,另外一个是200dp右对齐,中间留有10dp间隔,那么在Nexus5上面的显示效果就是下面这样
但是如果在Nexus S或者是Nexus One运行呢?下面是运行结果
可以看到,两个按钮发生了重叠。
我们都已经用了dp了,为什么会出现这种情况呢?
你听我慢慢道来。
虽然说dp可以去除不同像素密度的问题,使得1dp在不同像素密度上面的显示效果相同,但是还是由于Android屏幕设备的多样性,如果使用dp来作为度量单位,并不是所有的屏幕的宽度都是相同的dp长度,比如说,Nexus S和Nexus One属于hdpi,屏幕宽度是320dp,而Nexus 5属于xxhdpi,屏幕宽度是360dp,Galaxy Nexus属于xhdpi,屏幕宽度是384dp,Nexus 6 属于xxxhdpi,屏幕宽度是410dp。所以说,光Google自己一家的产品就已经有这么多的标准,而且屏幕宽度和像素密度没有任何关联关系,即使我们使用dp,在320dp宽度的设备和410dp的设备上,还是会有90dp的差别。当然,我们尽量使用match_parent和wrap_content,尽可能少的用dp来指定控件的具体长宽,再结合上权重,大部分的情况我们都是可以做到适配的。
但是除了这个方法,我们还有没有其他的更彻底的解决方案呢?
我们换另外一个思路来思考这个问题。
下面的方案来自Android Day Day Up 一群的【blue-深圳】,谢谢他的分享精神
因为分辨率不一样,所以不能用px;因为屏幕宽度不一样,所以要小心的用dp,那么我们可不可以用另外一种方法来统一单位,不管分辨率是多大,屏幕宽度用一个固定的值的单位来统计呢?
答案是:当然可以。
我们假设手机屏幕的宽度都是320某单位,那么我们将一个屏幕宽度的总像素数平均分成320份,每一份对应具体的像素就可以了。
具体如何来实现呢?我们看下面的代码
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;

public class MakeXml {

    private final static String rootPath = "C:\\Users\\Administrator\\Desktop\\layoutroot\\values-{0}x{1}\\";

    private final static float dw = 320f;
    private final static float dh = 480f;

    private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n";
    private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n";

    public static void main(String[] args) {
        makeString(320, 480);
        makeString(480,800);
        makeString(480, 854);
        makeString(540, 960);
        makeString(600, 1024);
        makeString(720, 1184);
        makeString(720, 1196);
        makeString(720, 1280);
        makeString(768, 1024);
        makeString(800, 1280);
        makeString(1080, 1812);
        makeString(1080, 1920);
        makeString(1440, 2560);
    }

    public static void makeString(int w, int h) {

        StringBuffer sb = new StringBuffer();
        sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        sb.append("<resources>");
        float cellw = w / dw;
        for (int i = 1; i < 320; i++) {
            sb.append(WTemplate.replace("{0}", i + "").replace("{1}",
                    change(cellw * i) + ""));
        }
        sb.append(WTemplate.replace("{0}", "320").replace("{1}", w + ""));
        sb.append("</resources>");

        StringBuffer sb2 = new StringBuffer();
        sb2.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        sb2.append("<resources>");
        float cellh = h / dh;
        for (int i = 1; i < 480; i++) {
            sb2.append(HTemplate.replace("{0}", i + "").replace("{1}",
                    change(cellh * i) + ""));
        }
        sb2.append(HTemplate.replace("{0}", "480").replace("{1}", h + ""));
        sb2.append("</resources>");

        String path = rootPath.replace("{0}", h + "").replace("{1}", w + "");
        File rootFile = new File(path);
        if (!rootFile.exists()) {
            rootFile.mkdirs();
        }
        File layxFile = new File(path + "lay_x.xml");
        File layyFile = new File(path + "lay_y.xml");
        try {
            PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));
            pw.print(sb.toString());
            pw.close();
            pw = new PrintWriter(new FileOutputStream(layyFile));
            pw.print(sb2.toString());
            pw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    public static float change(float a) {
        int temp = (int) (a * 100);
        return temp / 100f;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
代码应该很好懂,我们将一个屏幕宽度分为320份,高度480份,然后按照实际像素对每一个单位进行复制,放在对应values-widthxheight文件夹下面的lax.xml和lay.xml里面,这样就可以统一所有你想要的分辨率的单位了,下面是生成的一个320*480分辨率的文件,因为宽高分割之后总分数和像素数相同,所以x1就是1px,以此类推
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="x1">1.0px</dimen>
<dimen name="x2">2.0px</dimen>
<dimen name="x3">3.0px</dimen>
<dimen name="x4">4.0px</dimen>
<dimen name="x5">5.0px</dimen>
<dimen name="x6">6.0px</dimen>
<dimen name="x7">7.0px</dimen>
<dimen name="x8">8.0px</dimen>
<dimen name="x9">9.0px</dimen>
<dimen name="x10">10.0px</dimen>
...省略好多行
<dimen name="x300">300.0px</dimen>
<dimen name="x301">301.0px</dimen>
<dimen name="x302">302.0px</dimen>
<dimen name="x303">303.0px</dimen>
<dimen name="x304">304.0px</dimen>
<dimen name="x305">305.0px</dimen>
<dimen name="x306">306.0px</dimen>
<dimen name="x307">307.0px</dimen>
<dimen name="x308">308.0px</dimen>
<dimen name="x309">309.0px</dimen>
<dimen name="x310">310.0px</dimen>
<dimen name="x311">311.0px</dimen>
<dimen name="x312">312.0px</dimen>
<dimen name="x313">313.0px</dimen>
<dimen name="x314">314.0px</dimen>
<dimen name="x315">315.0px</dimen>
<dimen name="x316">316.0px</dimen>
<dimen name="x317">317.0px</dimen>
<dimen name="x318">318.0px</dimen>
<dimen name="x319">319.0px</dimen>
<dimen name="x320">320px</dimen>
</resources>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
那么1080*1960分辨率下是什么样子呢?我们可以看下,由于1080和320是3.37倍的关系,所以x1=3.37px
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="x1">3.37px</dimen>
<dimen name="x2">6.75px</dimen>
<dimen name="x3">10.12px</dimen>
<dimen name="x4">13.5px</dimen>
<dimen name="x5">16.87px</dimen>
<dimen name="x6">20.25px</dimen>
<dimen name="x7">23.62px</dimen>
<dimen name="x8">27.0px</dimen>
<dimen name="x9">30.37px</dimen>
<dimen name="x10">33.75px</dimen>
...省略好多行
<dimen name="x300">1012.5px</dimen>
<dimen name="x301">1015.87px</dimen>
<dimen name="x302">1019.25px</dimen>
<dimen name="x303">1022.62px</dimen>
<dimen name="x304">1026.0px</dimen>
<dimen name="x305">1029.37px</dimen>
<dimen name="x306">1032.75px</dimen>
<dimen name="x307">1036.12px</dimen>
<dimen name="x308">1039.5px</dimen>
<dimen name="x309">1042.87px</dimen>
<dimen name="x310">1046.25px</dimen>
<dimen name="x311">1049.62px</dimen>
<dimen name="x312">1053.0px</dimen>
<dimen name="x313">1056.37px</dimen>
<dimen name="x314">1059.75px</dimen>
<dimen name="x315">1063.12px</dimen>
<dimen name="x316">1066.5px</dimen>
<dimen name="x317">1069.87px</dimen>
<dimen name="x318">1073.25px</dimen>
<dimen name="x319">1076.62px</dimen>
<dimen name="x320">1080px</dimen>
</resources>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
无论在什么分辨率下,x320都是代表屏幕宽度,y480都是代表屏幕高度。
那么,我们应该如何使用呢?
首先,我们要把生成的所有values文件夹放到res目录下,当设计师把UI高清设计图给你之后,你就可以根据设计图上的尺寸,以某一个分辨率的机型为基础,找到对应像素数的单位,然后设置给控件即可。
下图还是两个Button,不同的是,我们把单位换成了我们在values文件夹下dimen的值,这样在你指定的分辨率下,不管宽度是320dp、360dp,还是410dp,就都可以完全适配了。
但是,还是有个问题,为什么下面的三个没有适配呢?
这是因为由于在生成的values文件夹里,没有对应的分辨率,其实一开始是报错的,因为默认的values没有对应dimen,所以我只能在默认values里面也创建对应文件,但是里面的数据却不好处理,因为不知道分辨率,我只好默认为x1=1dp保证尽量兼容。这也是这个解决方案的几个弊端,对于没有生成对应分辨率文件的手机,会使用默认values文件夹,如果默认文件夹没有,就会出现问题。
所以说,这个方案虽然是一劳永逸,但是由于实际上还是使用的px作为长度的度量单位,所以多少和google的要求有所背离,不好说以后会不会出现什么不可预测的问题。其次,如果要使用这个方案,你必须尽可能多的包含所有的分辨率,因为这个是使用这个方案的基础,如果有分辨率缺少,会造成显示效果很差,甚至出错的风险,而这又势必会增加软件包的大小和维护的难度,所以大家自己斟酌,择优使用。
更多信息可参考鸿洋的新文章Android 屏幕适配方案

提供备用位图

由于 Android 可在具有各种屏幕密度的设备上运行,因此我们提供的位图资源应始终可以满足各类普遍密度范围的要求:低密度、中等密度、高密度以及超高密度。这将有助于我们的图片在所有屏幕密度上都能得到出色的质量和效果。
要生成这些图片,我们应先提取矢量格式的原始资源,然后根据以下尺寸范围针对各密度生成相应的图片。
  • xhdpi:2.0
  • hdpi:1.5
  • mdpi:1.0(最低要求)
  • ldpi:0.75
也就是说,如果我们为 xhdpi 设备生成了 200x200 px尺寸的图片,就应该使用同一资源为 hdpi、mdpi 和 ldpi 设备分别生成 150x150、100x100 和 75x75 尺寸的图片。
然后,将生成的图片文件放在 res/ 下的相应子目录中(mdpi、hdpi、xhdpi、xxhdpi),系统就会根据运行您应用的设备的屏幕密度自动选择合适的图片。
这样一来,只要我们引用 @drawable/id,系统都能根据相应屏幕的 dpi 选取合适的位图。
还记得我们上面提到的图标设计尺寸吗?和这个其实是一个意思。
但是还有个问题需要注意下,如果是.9图或者是不需要多个分辨率的图片,就放在drawable文件夹即可,对应分辨率的图片要正确的放在合适的文件夹,否则会造成图片拉伸等问题。

实施自适应用户界面流程

前面我们介绍过,如何根据设备特点显示恰当的布局,但是这样做,会使得用户界面流程可能会有所不同。例如,如果应用处于双面板模式下,点击左侧面板上的项即可直接在右侧面板上显示相关内容;而如果该应用处于单面板模式下,点击相关的内容应该跳转到另外一个Activity进行后续的处理。所以我们应该按照下面的流程,一步步的完成自适应界面的实现。

确定当前布局

由于每种布局的实施都会稍有不同,因此我们需要先确定当前向用户显示的布局。例如,我们可以先了解用户所处的是“单面板”模式还是“双面板”模式。要做到这一点,可以通过查询指定视图是否存在以及是否已显示出来。
public class NewsReaderActivity extends FragmentActivity {
    boolean mIsDualPane;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);

        View articleView = findViewById(R.id.article);
        mIsDualPane = articleView != null &&
                        articleView.getVisibility() == View.VISIBLE;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
请注意,这段代码用于查询“报道”面板是否可用,与针对具体布局的硬编码查询相比,这段代码的灵活性要大得多。
再举一个适应各种组件的存在情况的方法示例:在对这些组件执行操作前先查看它们是否可用。例如,新闻阅读器示例应用中有一个用于打开菜单的按钮,但只有在版本低于 3.0 的 Android 上运行该应用时,这个按钮才会存在,因为 API 级别 11 或更高级别中的 ActionBar 已取代了该按钮的功能。因此,您可以使用以下代码为此按钮添加事件侦听器:
Button catButton = (Button) findViewById(R.id.categorybutton);
OnClickListener listener = /* create your listener here */;
if (catButton != null) {
    catButton.setOnClickListener(listener);
}
  • 1
  • 2
  • 3
  • 4
  • 5

根据当前布局做出响应

有些操作可能会因当前的具体布局而产生不同的结果。例如,在新闻阅读器示例中,如果用户界面处于双面板模式下,那么点击标题列表中的标题就会在右侧面板中打开相应报道;但如果用户界面处于单面板模式下,那么上述操作就会启动一个独立活动:
@Override
public void onHeadlineSelected(int index) {
    mArtIndex = index;
    if (mIsDualPane) {
        /* display article on the right pane */
        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    } else {
        /* start a separate activity */
        Intent intent = new Intent(this, ArticleActivity.class);
        intent.putExtra("catIndex", mCatIndex);
        intent.putExtra("artIndex", index);
        startActivity(intent);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
同样,如果该应用处于双面板模式下,就应设置带导航标签的操作栏;但如果该应用处于单面板模式下,就应使用下拉菜单设置导航栏。因此我们的代码还应确定哪种情况比较合适:
final String CATEGORIES[] = { "热门报道", "政治", "经济", "Technology" };

public void onCreate(Bundle savedInstanceState) {
    ....
    if (mIsDualPane) {
        /* use tabs for navigation */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
        int i;
        for (i = 0; i < CATEGORIES.length; i++) {
            actionBar.addTab(actionBar.newTab().setText(
                CATEGORIES[i]).setTabListener(handler));
        }
        actionBar.setSelectedNavigationItem(selTab);
    }
    else {
        /* use list navigation (spinner) */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
        SpinnerAdapter adap = new ArrayAdapter(this,
                R.layout.headline_item, CATEGORIES);
        actionBar.setListNavigationCallbacks(adap, handler);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

重复使用其他活动中的片段

多屏幕设计中的重复模式是指,对于某些屏幕配置,已实施界面的一部分会用作面板;但对于其他配置,这部分就会以独立活动的形式存在。例如,在新闻阅读器示例中,对于较大的屏幕,新闻报道文本会显示在右侧面板中;但对于较小的屏幕,这些文本就会以独立活动的形式存在。
在类似情况下,通常可以在多个活动中重复使用相同的 Fragment 子类以避免代码重复。例如,在双面板布局中使用了 ArticleFragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
然后又在小屏幕的Activity布局中重复使用了它 :
ArticleFragment frag = new ArticleFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
  • 1
  • 2
当然,这与在 XML 布局中声明片段的效果是一样的,但在这种情况下却没必要使用 XML 布局,因为报道片段是此活动中的唯一组件。
请务必在设计片段时注意,不要针对具体活动创建强耦合。要做到这一点,通常可以定义一个接口,该接口概括了相关片段与其主活动交互所需的全部方式,然后让主活动实施该界面:
例如,新闻阅读器应用的 HeadlinesFragment 会精确执行以下代码:
public class HeadlinesFragment extends ListFragment {
    ...
    OnHeadlineSelectedListener mHeadlineSelectedListener = null;

    /* Must be implemented by host activity */
    public interface OnHeadlineSelectedListener {
        public void onHeadlineSelected(int index);
    }
    ...

    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
        mHeadlineSelectedListener = listener;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
然后,如果用户选择某个标题,相关片段就会通知由主活动指定的侦听器(而不是通知某个硬编码的具体活动):
public class HeadlinesFragment extends ListFragment {
    ...
    @Override
    public void onItemClick(AdapterView<?> parent,
                            View view, int position, long id) {
        if (null != mHeadlineSelectedListener) {
            mHeadlineSelectedListener.onHeadlineSelected(position);
        }
    }
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
除此之外,我们还可以使用第三方框架,比如说使用“订阅-发布”模式的EventBus来更多的优化组件之间的通信,减少耦合。

处理屏幕配置变化

如果我们使用独立Activity实施界面的独立部分,那么请注意,我们可能需要对特定配置变化(例如屏幕方向的变化)做出响应,以便保持界面的一致性。
例如,在运行 Android 3.0 或更高版本的标准 7 英寸平板电脑上,如果新闻阅读器示例应用运行在纵向模式下,就会在使用独立活动显示新闻报道;但如果该应用运行在横向模式下,就会使用双面板布局。
也就是说,如果用户处于纵向模式下且屏幕上显示的是用于阅读报道的活动,那么就需要在检测到屏幕方向变化(变成横向模式)后执行相应操作,即停止上述活动并返回主活动,以便在双面板布局中显示相关内容:
public class ArticleActivity extends FragmentActivity {
    int mCatIndex, mArtIndex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);

        // If should be in two-pane mode, finish to return to main activity
        if (getResources().getBoolean(R.bool.has_two_panes)) {
            finish();
            return;
        }
        ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
通过上面几个步骤,我们就完全可以建立一个可以根据用户界面配置进行自适应的App了。

最佳实践

关于高清设计图尺寸

Google官方给出的高清设计图尺寸有两种方案,一种是以mdpi设计,然后对应放大得到更高分辨率的图片,另外一种则是以高分辨率作为设计大小,然后按照倍数对应缩小到小分辨率的图片。
根据经验,我更推荐第二种方法,因为小分辨率在生成高分辨率图片的时候,会出现像素丢失,我不知道是不是有方法可以阻止这种情况发生。
而分辨率可以以1280*720或者是1960*1080作为主要分辨率进行设计。

ImageView的ScaleType属性

设置不同的ScaleType会得到不同的显示效果,一般情况下,设置为centerCrop能获得较好的适配效果。

动态设置

有一些情况下,我们需要动态的设置控件大小或者是位置,比如说popwindow的显示位置和偏移量等,这个时候我们可以动态的获取当前的屏幕属性,然后设置合适的数值
public class ScreenSizeUtil {

    public static int getScreenWidth(Activity activity) {
        return activity.getWindowManager().getDefaultDisplay().getWidth();
    }

    public static int getScreenHeight(Activity activity) {
        return activity.getWindowManager().getDefaultDisplay().getHeight();
    }

}