首页

通过admin

【转载分享】八个移动产品设计必备网站

【本文系外部转贴,原文地址:http://www.web20share.com/2012/05/mobile-app-design-sites.html
大家接触和涉及到的移动产品的设计项目越来越多,相关的移动应用素材库和优秀网站变得十分重要。在这里转载八个移动产品设计必备网站。
—————————————————————————————————————————————————–
好吧,又在爱库上发现了很棒的专辑,和大家分享!移动产品设计人员一定需要大量的使用其他各类应用,并且需要在产品设计时大量参考其他的移动应用的产品设计,这时如果有一些网站可以将很多优秀应用的不同流程分类展示,那一定是移动产品设计人员必备的网站!

一、Patterns of Design


Patterns是一个分享ios应用UI界面的网站,专注于分享iOS应用UI界面的细节,按照设计元素进行分类,按照iOS常用功能对各类UI进行分类展示。(Via

链接:http://www.patternsofdesign.co.uk/

二、 iOS UI Patterns


Splashscreens / iOS UI Patterns (beta) ,整理/罗列了许多精彩的iOS 应用界面截图,并且按照分类将这些截图分类,比如Activity,Login,About,Calendar,Seeting,Share等各种类型的不同应用的实现效果。(Via

链接:http://pttrns.com/

 三、Appsites

优秀移动应用网站设计展示,非常的赞!

链接:http://www.appsites.com/

四、Dribbble

Dribbble应该大家都比较熟悉,是一个设计师交流和分享自己设计作品的社区。上面有很多非常棒的移动产品设计作品。

链接:http://dribbble.com/

五、Tappgala


分享最棒的手机产品界面设计,做手机产品的朋友们不可错过这个站。

链接:http://www.tappgala.com/

六、Mobile Design Pattern Gallery


移动设计书籍、移动原型分享的网站。

链接:http://www.mobiledesignpatterngallery.com/

七、Code4App


Code4App是一个移动平台的代码库。我们目前只推出ios平台,会慢慢加入其他移动平台,如Android,WP。Code4App收集了iOS平台几百个代码,并且配有效果图和演示视频。

链接:http://code4app.com/

八、iOS Inspries Me


主要是展示优秀的iOS平台上应用的设计,icon及相关资源。Showcase of the best looking iPhone & iPad app icons, app interfaces, app websites & resources

链接:http://www.iosinspires.me/

更多可以查看这里:http://ikeepu.com/list/63970

通过admin

八款开源ANDROID游戏引擎

很多初学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于 iPhone下有诸如Cocos2d-iphone之类的免费游戏引擎可供使用,一边自暴自弃的抱怨Android平台游戏开发难度太高,又连个像样的游戏引擎也没有,甚至误以为使用Java语言开发游戏是一件费力不讨好且没有出路的事情。

事实上,这种想法完全是没有必要且不符合实际的,作为能和苹果iOS分庭抗礼的Android(各种意义上),当然也会有相当数量的游戏引擎存在。仅仅因为我们处于这个狭小的天地间,与外界接触不够,所以对它们的存在茫然不知罢了。

 

下面我就罗列出八款常见的Android游戏引擎,以供有需要者参考(收费,下载量过小,不公布源码,以及鄙人不知道(-_-)的引擎不在此列)。

 

1、Angle

 

Angle是一款专为Android平台设计的,敏捷且适合快速开发的2D游戏引擎,基于OpenGL ES技术开发。该引擎全部用Java代码编写,并且可以根据自己的需要替换里面的实现,缺陷在于文档不足,而且下载的代码中仅仅包含有少量的示例教程。

 

最低运行环境要求不详。

 

项目地址:http://code.google.com/p/angle/

 

2、Rokon

 

rokon是一款Android 2D游戏引擎,基于OpenGL ES技术开发,物理引擎为Box2D,因此能够实现一些较为复杂的物理效果,该项目最新版本为 2.0.3 (09/07/10)。总体来说,此引擎最大的优点在于其开发文档相当之完备,并且项目作者对反馈Bug的修正非常之神速,所以该框架的使用在目前也最为广泛,有人干脆将它称为Cocos2d-iPhone引擎的Android版(业务逻辑和编码风格上也确实很像)。附带一提,国内某个需要注册会员才能下载的Android游戏框架衍生于此框架,所以大家也不要刻板的认为收费便一定是好的,免费就一定不好。

 

最低运行环境要求为Android 1.5。

 

项目地址:http://code.google.com/p/rokon/

 

3、LGame

 

LGame是一款国人开发的Java游戏引擎,有Android及PC(J2SE)两个开发版本,目前最高版本同为0.2.6(31/07/10)。其底层绘图器LGrpaphics封装有J2SE以及J2ME提供的全部Graphics API(PC版采用Graphics2D封装,Android版采用Canvas模拟实现),所以能够将J2SE或J2ME开发经验直接套用其中,两版本间主要代码能够相互移植。Android版内置有Admob接口,可以不必配置XML直接硬编码Admob广告信息。

 

该引擎除了基本的音效、图形、物理、精灵等常用组件以外,也内置有Ioc、xml、http等常用Java组件的封装,代价是jar体积较为庞大,PC版已突破1.2MB,Android版有所简化也在500KB左右。此外,该引擎还内置有按照1:1实现的J2ME精灵类及相关组件,可以将绝大多数 J2ME游戏平移到Android或PC版中。唯一遗憾的是,该项目作者是个极其懒惰的家伙,开发文档从去年说到今年依旧没有提供,只有游戏示例可供下载。

 

最低运行环境要求为Android 1.1。

 

项目地址:http://code.google.com/p/loon-simple/

 

4、AndEngine

 

andengine同样是一款基于OpenGL ES技术的Android游戏引擎,物理引擎同样为Box2D(标配|||)。该框架性能普通,文档缺乏,但示例较为丰富。

 

下载地址(未直接提供jar下载,源码可通过svn提取):http://code.google.com/p/andengine/

 

最低运行环境要求不详。

 

项目地址:http://code.google.com/p/rokon/

 

5、libgdx

 

libgdx是一款基于OpenGL ES技术开发的Android游戏引擎,支持Android平台下的2D游戏开发,物理引擎采用Box2D实现。单就性能角度来说,堪称是一款非常强大的 Android游戏引擎,但缺陷在于精灵类等相关组件在使用上不够简化,而且文档也较为匮乏。

 

最低运行环境要求不详。

 

项目地址:http://code.google.com/p/libgdx/

 

6、jPCT

 

jPCT是一款基于OpenGL技术开发的3D图形引擎(PC环境为标准OpenGL,Android为OpenGL ES),以Java语言为基础的,拥有功能强大的Java 3D解决方案。该引擎与LGame(此为2D游戏引擎)相类似,目前拥有PC(J2SE)以及Android两个开发版本。

 

jPCT的最大优势之一,就在于它惊人的向下兼容性。在PC环境中,jPCT甚至可以运行在JVM1.1环境之中,因为jPCT内部提供的图形渲染接口完全符合所有的Java 1.1规范(就连已经消失的Microsoft VM乃至更古老的Netscape 4 VM也不例外)。

 

最低运行环境要求为Android 1.5。

 

项目地址:http://www.jpct.net/jpct-ae/

 

7、Alien3d

 

Alien3d是一款体积非常之小的Android 3D游戏引擎,基于OpenGL ES技术开发。为了压缩体积,它根据不同功能采用多jar方式发布(包括alien3d-engine.jar,alien3d- tiled.jar,alien3d-sprites.jar,alien3d-shapes.jar,alien3d- particles2d.jar,),事实上它的核心文件大约只有40KB,所有相关jar的总和也不足150KB。

 

最低运行环境要求为Android 1.5。

 

项目地址:http://code.google.com/p/alien3d/

 

8、Catcake

 

Catcake是一款跨平台的Java 3D图形引擎,目前支持PC(J2SE)及Android环境运行(已有iPhone版规划)。该引擎在易用性和运行性能上皆有出色的表现,支持常见的游戏开发功能,诸如精灵动画,音频处理和视频播放等。

 

最低运行环境要求为Android 1.6。

 

项目地址:http://code.google.com/p/catcake/

 

源文档 <http://www.cnblogs.com/henryhu/archive/2011/02/10/1950983.html>

通过admin

linux cat 命令详解

使用方式:cat [-AbeEnstTuv] [–help] [–version] fileName

说明:把档案串连接后传到基本输出(萤幕或加 > fileName 到另一个档案)

参数:

-n 或 –number 由 1 开始对所有输出的行数编号

-b 或 –number-nonblank 和 -n 相似,只不过对于空白行不编号

-s 或 –squeeze-blank 当遇到有连续两行以上的空白行,就代换为一行的空白行

-v 或 –show-nonprinting

范例:

cat -n textfile1 > textfile2 把 textfile1 的档案内容加上行号后输入 textfile2 这个档案里

cat -b textfile1 textfile2 >> textfile3 把 textfile1 和 textfile2 的档案内容加上行号(空白行不加)之后将内容附加到 textfile3 里。

范例:

把 textfile1 的档案内容加上行号后输入 textfile2 这个档案里

cat -n textfile1 > textfile2

把 textfile1 和 textfile2 的档案内容加上行号(空白行不加)之后将内容附加到 textfile3 里。

cat -b textfile1 textfile2 >> textfile3

cat /dev/null > /etc/test.txt 此为清空/etc/test.txt档案内容

cat 也可以用来制作 image file。例如要制作软碟的 image file,将软碟放好后打

cat /dev/fd0 > OUTFILE

相反的,如果想把 image file 写到软碟,请打

cat IMG_FILE > /dev/fd0

注:

1. OUTFILE 指输出的 image 档名。

2. IMG_FILE 指 image file。

3. 若从 image file 写回 device 时,device 容量需与相当。

4. 通常用在制作开机磁片。

 

cat主要有三大功能:

1.一次显示整个文件。$ cat   filename

2.从键盘创建一个文件。$ cat  >  filename

只能创建新文件,不能编辑已有文件.

3.将几个文件合并为一个文件。 $cat   file1   file2  > file

参数:

-n 或 –number 由 1 开始对所有输出的行数编号

-b 或 –number-nonblank 和 -n 相似,只不过对于空白行不编号

-s 或 –squeeze-blank 当遇到有连续两行以上的空白行,就代换为一行的空白行

-v 或 –show-nonprinting

范例:

cat -n textfile1 > textfile2 把 textfile1 的档案内容加上行号后输入 textfile2 这个档案里

cat -b textfile1 textfile2 >> textfile3 把 textfile1 和 textfile2 的档案内容加上行号(空白行不加)之后将内容附加到 textfile3 里。

范例:

把 textfile1 的档案内容加上行号后输入 textfile2 这个档案里

cat -n textfile1 > textfile

把 textfile1 和 textfile2 的档案内容加上行号(空白行不加)之后将内容附加到 textfile3 里

cat -b textfile1 textfile2 >> textfile3

cat /dev/null > /etc/test.txt 此为清空/etc/test.txt档案内容

cat 也可以用来制作 image file。例如要制作软碟的 image file,将软碟放好后打

cat /dev/fd0 > OUTFILE %W

相反的,如果想把 image file 写到软碟,请打

cat IMG_FILE > /dev/fd0

注: &copy;Newboys — Newboys综合论坛

1. OUTFILE 指输出的 image 档名。

2. IMG_FILE 指 image file。

3. 若从 image file 写回 device 时,device 容量需与相当。

4. 通常用在制作开机磁片。

13.9. 使用 cat 来操作文件

Red Hat Linux 有一个工具程序,它能够帮助你保留简短列表,将这些列表收集起来,甚至向你透漏一点你的系统信息。

这个工具叫做 cat,它是 concatenate(连锁)的简写,意思是合并文件。

cat 命令还会在屏幕上显示整个文件的内容(譬如,键入 cat filename.txt)。如果文件较长,它会在屏幕上飞快地滚过。要防止这一效果的发生,使用 cat filename.txt | less 命令。

一起使用管道(|)和 less 命令会一页一页地显示文件。然后,你便可以使用向上或向下的箭头键在页码中向前或向后移动。关于使用管道来合并两个不同功能的详细信息,请参阅

第 13.10 节 

13.9.1. 使用重导向

重导向就是使 shell 改变它所认定的标准输出,或者改变标准输出的目标。

要重导向标准输出,使用 > 符号。把 > 符号放在 cat 命令之后(或在任何写入标准输出的工具程序和应用程序之后),会把它的输出重导向到跟在符号之后的文件中。

譬如,使用 cat 自身会在屏幕上输出你所输入的内容,如同是在重复你刚键入的行。下面的例子显示了 cat 会重复你输入的每一行:

 

图 13-5. cat 命令

要把 cat 的输出重导向到一个文件中,在 shell 提示下键入以下命令(按 [Enter] 键会把你带到一个空行):

cat > sneakers.txt

 

图 13-6. 把输出重导向到一个文件

按 [Enter] 键转到一个空行,然后使用 [Ctrl]-[D] 键来退出 cat。

注意到

图 13-6 

中的区别了吗?此处并没有重复显示。这是因为 cat 的标准输出已经被重导向了。重导向的地方是你刚刚制作的一个叫做 sneakers.txt 的崭新文件。

当你运行 cat 命令时,你会发现你所在目录中的文件

如前所示,你可以使用 cat 来读取文件。在提示下,键入:

cat sneakers.txt

 

小心

 

在你把输出重导向入文件时,请谨慎从事,因为你会很容易地覆盖一个现存文件!除非你想代替该文件,请确保你所创建的文件名与已经存在的文件名不一样。

再把输出重导向到另一个文件,暂且把它叫做 home.txt。在这个例子中,键入命令 cat > home.txt,然后按 [Enter],其后跟随:

bring the coffee home

take off shoes

put on sneakers

make some coffee

relax!

现在,在一个空行上,使用 [Ctrl]-[D] 键组合来退出 cat。

下一步,使用 cat 把 home.txt 和 sneakers.txt 连接起来,然后再把两个文件的输出重导向到一个叫做 saturday.txt 的新文件(你会在

图 13-7 

中发现一个示例)。键入下面的命令:

cat sneakers.txt home.txt > saturday.txt

 

图 13-7. 连接文件和重导向输出

你可以看到 cat 已经把 home.txt 添加到 sneakers.txt 的结尾处。

13.9.2. 后补标准输出

你可以使用输出重导向来在一个现存文件之后添加新信息。这与你使用 > 符号相似,你是在告诉 shell 把信息发送到标准输出之外的某个地方。

然而,当你使用 >> 时,你是在给文件添加信息,而不是完全替换文件内容。

最好的解释方法是向你演示实例。我们便使用刚才已创建的两个文件(sneakers.txt 和 home.txt),然后使用后补输出的符号把它们连接起来。你想把 home.txt 的信息添加到 sneakers.txt 的信息中去,因此键入:

cat home.txt >> sneakers.txt

现在,使用 cat sneakers.txt 的命令来检查一下。最终的输出在文件结尾处显示了 home.txt 的内容:

buy some sneakers

then go to the coffee shop

then buy some coffee

bring the coffee home

take off shoes

put on sneakers

make some coffee

relax!

你键入的命令把文件 home.txt 的输出后补到文件 sneakers.txt 中去。

通过后补输出,你利用了现存文件而不必创建新文件,从而为自己节省些时间(以及一些磁盘群集)。

现在比较一下文件 sneakers.txt 和文件 saturday.txt 的结果,你就会看到它们一模一样。要做比较,键入:

cat sneakers.txt; cat saturday.txt

这两个文件的内容都会被显示 — 先是 sneakers.txt 文件,然后是 saturday.txt 文件(如

图 13-8 

所示)。

 

图 13-8. 串联命令和比较文件

13.9.3. 重导向标准输入

你不但可以重导向标准输出,还可以重导向标准输入。

当你使用重导向标准输入符号

cat

因为你用来分隔 cat 命令和文件的是小于号(sneakers.txt 的输出就被 cat 命令读取。

 

图 13-9. 重导向标准输入

 

源文档 <http://blog.csdn.net/mecho/article/details/4325691>

 

通过admin

linux grep命令参数及用法详解—linux管道命令grep

功能说明:查找文件里符合条件的字符串。

语  法:grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][–help][范本样式][文件或目录…]

补充说明:grep 指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设grep指令会把含有范本样式的那一列显示出来。若不指定任何文件名称,或是所给予的文件名为“-”,则grep指令会从标准输入设备读取数据。

参  数:
-a或–text   不要忽略二进制的数据。
-A<显示列数>或–after-context=<显示列数>   除了显示符合范本样式的那一列之外,并显示该列之后的内容。
-b或–byte-offset   在显示符合范本样式的那一列之前,标示出该列第一个字符的位编号。
-B<显示列数>或–before-context=<显示列数>   除了显示符合范本样式的那一列之外,并显示该列之前的内容。
-c或–count   计算符合范本样式的列数。
-C<显示列数>或–context=<显示列数>或-<显示列数>   除了显示符合范本样式的那一列之外,并显示该列之前后的内容。
-d<进行动作>或–directories=<进行动作>   当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。
-e<范本样式>或–regexp=<范本样式>   指定字符串做为查找文件内容的范本样式。
-E或–extended-regexp   将范本样式为延伸的普通表示法来使用。
-f<范本文件>或–file=<范本文件>   指定范本文件,其内容含有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每列一个范本样式。
-F或–fixed-regexp   将范本样式视为固定字符串的列表。
-G或–basic-regexp   将范本样式视为普通的表示法来使用。
-h或–no-filename   在显示符合范本样式的那一列之前,不标示该列所属的文件名称。
-H或–with-filename   在显示符合范本样式的那一列之前,表示该列所属的文件名称。
-i或–ignore-case   忽略字符大小写的差别。
-l或–file-with-matches   列出文件内容符合指定的范本样式的文件名称。
-L或–files-without-match   列出文件内容不符合指定的范本样式的文件名称。
-n或–line-number   在显示符合范本样式的那一列之前,标示出该列的列数编号。
-q或–quiet或–silent   不显示任何信息。
-r或–recursive   此参数的效果和指定“-d recurse”参数相同。
-s或–no-messages   不显示错误信息。
-v或–revert-match   反转查找。
-V或–version   显示版本信息。
-w或–word-regexp   只显示全字符合的列。
-x或–line-regexp   只显示全列符合的列。
-y   此参数的效果和指定“-i”参数相同。
–help   在线帮助。

linux grep命令的使用
用grep命令 搜索文本文件 来自www.linuxso.com

如果您要在几个文本文件中查找一字符串,可以使用&lsquo;grep’命令。‘grep’在文本中搜索指定的字符串。
假设您正在‘/usr/src/linux/Documentation’目录下搜索带字符串‘magic’的文件:
$ grep magic /usr/src/linux/Documentation/*
sysrq.txt:* How do I enable the magic SysRQ key?
sysrq.txt:* How do I use the magic SysRQ key?
其中文件‘sysrp.txt’包含该字符串,讨论的是 SysRQ 的功能。
默认情况下,‘grep’只搜索当前目录。如果此目录下有许多子目录,‘grep’会以如下形式列出:
grep: sound: Is a directory
这可能会使‘grep’的输出难于阅读。这里有两种解决的办法:
明确要求搜索子目录:grep -r
或忽略子目录:grep -d skip
当然,如果预料到有许多输出,您可以通过 管道 将其转到‘less’上阅读
$ grep magic /usr/src/linux/Documentation/* | less
这样,您就可以更方便地阅读。
有一点要注意,您必需提供一个文件过滤方式(搜索全部文件的话用 *)。如果您忘了,‘grep’会一直等着,直到该程序被中断。如果您遇到了这样的情况,按 <CTRL c> ,然后再试。
下面是一些有意思的命令行参数:
grep -i pattern files :不区分大小写地搜索。默认情况区分大小写,
grep -l pattern files :只列出匹配的文件名,
grep -L pattern files :列出不匹配的文件名,
grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配‘magic’,而不是‘magical’),
grep -C number pattern files :匹配的上下文分别显示[number]行,
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。
这里还有些用于搜索的特殊符号:
< 和 > 分别标注单词的开始与结尾。
例如:
grep man * 会匹配 ‘Batman’、‘manic’、‘man’等,
grep \'<man\’ * 匹配‘manic’和‘man’,但不是‘Batman’,
grep \'<man>\’ 只匹配‘man’,而不是‘Batman’或‘manic’等其他的字符串。
\’^\’:指匹配的字符串在行首,
\’$\’:指匹配的字符串在行尾,
如果您不习惯命令行参数,可以试试图形界面的‘grep’,如 reXgrep 。这个软件提供 AND、OR、NOT 等语法,还有漂亮的按钮 🙂 。如果您只是需要更清楚的输出,不妨试试 fungrep 。

.grep 搜索字符串
命令格式:
grep string filename
寻找字串的方法很多,比如说我想找所有以M开头的行.此时必须引进pattern的观
念.以下是一些简单的□例,以及说明:
^M 以M开头的行,^表示开始的意思
M$ 以M结尾的行,$表示结束的意思
^[0-9] 以数字开始的行,[]内可列举字母
^[124ab] 以1,2,4,a,或b开头的行
^b.503 句点表示任一字母
* 星号表示0个以上的字母(可以没有)
+ 加号表示1个以上的字母
. 斜线可以去掉特殊意义
<eg> cat passwd | grep ^b 列出大学部有申请帐号者名单
cat passwd | grep ^s 列出交换学生申请帐号者名单
cat passwd | grep \’^b.503\’ 列出电机系各年级…
grep \’^.\’ myfile.txt 列出所有以句点开头的行

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. grep简介

 

grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。Unix的grep家族包 括grep、egrepfgrep。egrep和fgrep的命令只跟grep有很小不同。egrep是grep的扩展,支持更多的re元字符, fgrep就是fixed grep或fast grep,它们把所有的字母都看作单词,也就是说,正则表达式中的元字符表示回其自身的字面意义,不再特殊。linux使用GNU版本的grep。它功能 更强,可以通过-G、-E、-F命令行选项来使用egrep和fgrep的功能。

grep的工作方式是这样的,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到屏幕,不影响原文件内容。

grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。
2. grep正则表达式元字符集(基本集)

 

^

锚定行的开始 如:\’^grep\’匹配所有以grep开头的行。

$

锚定行的结束 如:\’grep$\’匹配所有以grep结尾的行。

匹配一个非换行符的字符 如:\’gr.p\’匹配gr后接一个任意字符,然后是p。

*

匹配零个或多个先前字符 如:\’*grep\’匹配所有一个或多个空格后紧跟grep的行。 .*一起用代表任意字符。

[]

匹配一个指定范围内的字符,如\'[Gg]rep\’匹配Grep和grep。

[^]

匹配一个不在指定范围内的字符,如:\'[^A-FH-Z]rep\’匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行。

(..)

标记匹配字符,如\'(love)\’,love被标记为1。

<

锚定单词的开始,如:\’

>

锚定单词的结束,如\’grep>\’匹配包含以grep结尾的单词的行。

x{m}

重复字符x,m次,如:\’0{5}\’匹配包含5个o的行。

x{m,}

重复字符x,至少m次,如:\’o{5,}\’匹配至少有5个o的行。

x{m,n}

重复字符x,至少m次,不多于n次,如:\’o{5,10}\’匹配5–10个o的行。

w

匹配文字和数字字符,也就是[A-Za-z0-9],如:\’Gw*p\’匹配以G后跟零个或多个文字或数字字符,然后是p。

W

w的反置形式,匹配一个或多个非单词字符,如点号句号等。

 

b

单词锁定符,如: \’bgrepb\’只匹配grep。

3. 用于egrep和 grep -E的元字符扩展集

+

匹配一个或多个先前的字符。如:\'[a-z]+able\’,匹配一个或多个小写字母后跟able的串,如loveable,enable,disable等。

?

匹配零个或多个先前的字符。如:\’gr?p\’匹配gr后跟一个或没有字符,然后是p的行。

a|b|c

匹配a或b或c。如:grep|sed匹配grep或sed

()

分组符号,如:love(able|rs)ov+匹配loveable或lovers,匹配一个或多个ov。

x{m},x{m,},x{m,n}

作用同x{m},x{m,},x{m,n}

4. POSIX字符类

为了在不同国家的字符编码中保持一至,POSIX(The Portable Operating System Interface)增加了特殊的字符类,如[:alnum:]是A-Za-z0-9的另一个写法。要把它们放到[]号内才能成为正则表达式,如[A- Za-z0-9]或[[:alnum:]]。在linux下的grep除fgrep外,都支持POSIX的字符类。

[:alnum:]

文字数字字符

[:alpha:]

文字字符

[:digit:]

数字字符

[:graph:]

非空字符(非空格、控制字符)

[:lower:]

小写字符

[:cntrl:]

控制字符

[:print:]

非空字符(包括空格)

[:punct:]

标点符号

[:space:]

所有空白字符(新行,空格,制表符)

[:upper:]

大写字符

[:xdigit:]

十六进制数字(0-9,a-f,A-F)

5. Grep命令选项

-?

同时显示匹配行上下的?行,如:grep -2 pattern filename同时显示匹配行的上下2行。

-b,–byte-offset

打印匹配行前面打印该行所在的块号码。

-c,–count

只打印匹配的行数,不显示匹配的内容。

-f File,–file=File

从文件中提取模板。空文件中包含0个模板,所以什么都不匹配。

-h,–no-filename

当搜索多个文件时,不显示匹配文件名前缀。

-i,–ignore-case

忽略大小写差别。

-q,–quiet

取消显示,只返回退出状态。0则表示找到了匹配的行。

-l,–files-with-matches

打印匹配模板的文件清单。

-L,–files-without-match

打印不匹配模板的文件清单。

-n,–line-number

在匹配的行前面打印行号。

-s,–silent

不显示关于不存在或者无法读取文件的错误信息。

-v,–revert-match

反检索,只显示不匹配的行。

-w,–word-regexp

如果被<和>引用,就把表达式做为一个单词搜索。

-V,–version

显示软件版本信息。

6. 实例

要用好grep这个工具,其实就是要写好正则表达式,所以这里不对grep的所有功能进行实例讲解,只列几个例子,讲解一个正则表达式的写法。

$ ls -l | grep \’^a\’

通过管道过滤ls -l输出的内容,只显示以a开头的行。

$ grep \’test\’ d*

显示所有以d开头的文件中包含test的行。

$ grep \’test\’ aa bb cc

显示在aa,bb,cc文件中匹配test的行。

$ grep \'[a-z]{5}\’ aa

显示所有包含每个字符串至少有5个连续小写字符的字符串的行。

$ grep \’w(es)t.*1\’ aa

如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着另外一个es(1),找到就显示该行。如果用egrep或grep -E,就不用””号进行转义,直接写成\’w(es)t.*1\’就可以了。

http://www.linuxso.com/command/grep.html

linux grep命令参数及用法详解—linux管道命令grep

通过admin

Android获取系统cpu信息,内存,版本,电量等信息

1、CPU频率,CPU信息:/proc/cpuinfo和/proc/stat

通过读取文件/proc/cpuinfo系统CPU的类型等多种信息。

读取/proc/stat 所有CPU活动的信息来计算CPU使用率

 

下面我们就来讲讲如何通过代码来获取CPU频率:

package com.orange.cpu;

 

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.InputStream;

 

public class CpuManager {

 

// 获取CPU最大频率(单位KHZ)

// “/system/bin/cat” 命令行

// “/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq” 存储最大频率的文件的路径

public static String getMaxCpuFreq() {

String result = “”;

ProcessBuilder cmd;

try {

String[] args = { “/system/bin/cat”,

“/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq” };

cmd = new ProcessBuilder(args);

Process process = cmd.start();

InputStream in = process.getInputStream();

byte[] re = new byte[24];

while (in.read(re) != -1) {

result = result + new String(re);

}

in.close();

} catch (IOException ex) {

ex.printStackTrace();

result = “N/A”;

}

return result.trim();

}

 

// 获取CPU最小频率(单位KHZ)

public static String getMinCpuFreq() {

String result = “”;

ProcessBuilder cmd;

try {

String[] args = { “/system/bin/cat”,

“/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq” };

cmd = new ProcessBuilder(args);

Process process = cmd.start();

InputStream in = process.getInputStream();

byte[] re = new byte[24];

while (in.read(re) != -1) {

result = result + new String(re);

}

in.close();

} catch (IOException ex) {

ex.printStackTrace();

result = “N/A”;

}

return result.trim();

}

 

// 实时获取CPU当前频率(单位KHZ)

public static String getCurCpuFreq() {

String result = “N/A”;

try {

FileReader fr = new FileReader(

“/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq”);

BufferedReader br = new BufferedReader(fr);

String text = br.readLine();

result = text.trim();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return result;

}

 

// 获取CPU名字

public static String getCpuName() {

try {

FileReader fr = new FileReader(“/proc/cpuinfo”);

BufferedReader br = new BufferedReader(fr);

String text = br.readLine();

String[] array = text.split(“:\\s+”, 2);

for (int i = 0; i < array.length; i++) {

}

return array[1];

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

}

 

2、内存:/proc/meminfo

public void getTotalMemory() {  
        String str1 = "/proc/meminfo";  
        String str2="";  
        try {  
            FileReader fr = new FileReader(str1);  
            BufferedReader localBufferedReader = new BufferedReader(fr, 8192);  
            while ((str2 = localBufferedReader.readLine()) != null) {  
                Log.i(TAG, "---" + str2);  
            }  
        } catch (IOException e) {  
        }  
    }

3、Rom大小

public long[] getRomMemroy() {  
        long[] romInfo = new long[2];  
        //Total rom memory  
        romInfo[0] = getTotalInternalMemorySize();  

        //Available rom memory  
        File path = Environment.getDataDirectory();  
        StatFs stat = new StatFs(path.getPath());  
        long blockSize = stat.getBlockSize();  
        long availableBlocks = stat.getAvailableBlocks();  
        romInfo[1] = blockSize * availableBlocks;  
        getVersion();  
        return romInfo;  
    }  

    public long getTotalInternalMemorySize() {  
        File path = Environment.getDataDirectory();  
        StatFs stat = new StatFs(path.getPath());  
        long blockSize = stat.getBlockSize();  
        long totalBlocks = stat.getBlockCount();  
        return totalBlocks * blockSize;  
    }

4、sdCard大小

public long[] getSDCardMemory() {  
        long[] sdCardInfo=new long[2];  
        String state = Environment.getExternalStorageState();  
        if (Environment.MEDIA_MOUNTED.equals(state)) {  
            File sdcardDir = Environment.getExternalStorageDirectory();  
            StatFs sf = new StatFs(sdcardDir.getPath());  
            long bSize = sf.getBlockSize();  
            long bCount = sf.getBlockCount();  
            long availBlocks = sf.getAvailableBlocks();  

            sdCardInfo[0] = bSize * bCount;//总大小  
            sdCardInfo[1] = bSize * availBlocks;//可用大小  
        }  
        return sdCardInfo;  
    }

5、电池电量

private BroadcastReceiver batteryReceiver=new BroadcastReceiver(){  

        @Override  
        public void onReceive(Context context, Intent intent) {  
            int level = intent.getIntExtra("level", 0);  
            //  level加%就是当前电量了  
    }  
    };  
registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

6、系统的版本信息

public String[] getVersion(){  
    String[] version={"null","null","null","null"};  
    String str1 = "/proc/version";  
    String str2;  
    String[] arrayOfString;  
    try {  
        FileReader localFileReader = new FileReader(str1);  
        BufferedReader localBufferedReader = new BufferedReader(  
                localFileReader, 8192);  
        str2 = localBufferedReader.readLine();  
        arrayOfString = str2.split("\\s+");  
        version[0]=arrayOfString[2];//KernelVersion  
        localBufferedReader.close();  
    } catch (IOException e) {  
    }  
    version[1] = Build.VERSION.RELEASE;// firmware version  
    version[2]=Build.MODEL;//model  
    version[3]=Build.DISPLAY;//system version  
    return version;  
}

7、mac地址和开机时间

public String[] getOtherInfo(){  
    String[] other={"null","null"};  
       WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);  
       WifiInfo wifiInfo = wifiManager.getConnectionInfo();  
       if(wifiInfo.getMacAddress()!=null){  
        other[0]=wifiInfo.getMacAddress();  
    } else {  
        other[0] = "Fail";  
    }  
    other[1] = getTimes();  
       return other;  
}  
private String getTimes() {  
    long ut = SystemClock.elapsedRealtime() / 1000;  
    if (ut == 0) {  
        ut = 1;  
    }  
    int m = (int) ((ut / 60) % 60);  
    int h = (int) ((ut / 3600));  
    return h + " " + mContext.getString(R.string.info_times_hour) + m + " "  
            + mContext.getString(R.string.info_times_minute);  
}

 

 

部分内容转载自:

http://gqdy365.iteye.com/blog/1066113

http://blog.csdn.net/chuxing/article/details/7571547

通过admin

Android 中使用自定义字体的方法

1、Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace

2、在Android中可以引入其他字体 。

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:Android="http://schemas.android.com/apk/res/android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent" >

    <TableRow>

        <TextView
            Android:layout_marginRight="4px"
            Android:text="sans:"
            Android:textSize="20sp" >
        </TextView>
        <!-- 使用默认的sans字体 -->

        <TextView
            Android:id="@+id/sans"
            Android:text="Hello,World"
            Android:textSize="20sp"
            Android:typeface="sans" >
        </TextView>
    </TableRow>

    <TableRow>

        <TextView
            Android:layout_marginRight="4px"
            Android:text="serif:"
            Android:textSize="20sp" >
        </TextView>
        <!-- 使用默认的serifs字体 -->

        <TextView
            Android:id="@+id/serif"
            Android:text="Hello,World"
            Android:textSize="20sp"
            Android:typeface="serif" >
        </TextView>
    </TableRow>

    <TableRow>

        <TextView
            Android:layout_marginRight="4px"
            Android:text="monospace:"
            Android:textSize="20sp" >
        </TextView>
        <!-- 使用默认的monospace字体 -->

        <TextView
            Android:id="@+id/monospace"
            Android:text="Hello,World"
            Android:textSize="20sp"
            Android:typeface="monospace" >
        </TextView>
    </TableRow>
    <!-- 这里没有设定字体,我们将在Java代码中设定 -->

    <TableRow>

        <TextView
            Android:layout_marginRight="4px"
            Android:text="custom:"
            Android:textSize="20sp" >
        </TextView>

        <TextView
            Android:id="@+id/custom"
            Android:text="Hello,World"
            Android:textSize="20sp" >
        </TextView>
    </TableRow>

</TableLayout>
// 得到TextView控件对象
TextView textView = (TextView) findViewById(R.id.custom);
// 将字体文件保存在assets/fonts/目录下,www.linuxidc.com创建Typeface对象
Typeface typeFace = Typeface.createFromAsset(getAssets(),"fonts/DroidSansThai.ttf");
// 应用字体
textView.setTypeface(typeFace);

如果想对整个界面的所有控件都应用自定义字体,可以:

package arui.blog.csdn.net;  

import android.app.Activity;  
import android.graphics.Typeface;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.TextView;  

public class FontManager {  

    public static void changeFonts(ViewGroup root, Activity act) {  

       Typeface tf = Typeface.createFromAsset(act.getAssets(),  
              "fonts/xxx.ttf");  

       for (int i = 0; i < root.getChildCount(); i++) {  
           View v = root.getChildAt(i);  
           if (v instanceof TextView) {  
              ((TextView) v).setTypeface(tf);  
           } else if (v instanceof Button) {  
              ((Button) v).setTypeface(tf);  
           } else if (v instanceof EditText) {  
              ((EditText) v).setTypeface(tf);  
           } else if (v instanceof ViewGroup) {  
              changeFonts((ViewGroup) v, act);  
           }  
       }  

    }  
}

 

通过admin

Android实现多页左右滑动效果,支持子view动态创建和cache

要实现多页滑动效果,主要是需要处理onTouchEvent和onInterceptTouchEvent,要处理好touch事件的子控件和父控件的传递问题。滚动控制可以利用android的Scroller来实现。

对于不清楚android Touch事件的传递过程的,先google一下。

这里提供两种做法:

1、自定义MFlipper控件,从ViewGroup继承,利用Scroller实现滚动,重点是onTouchEvent和onInterceptTouchEvent的重写,要注意什么时候该返回true,什么时候false。否则会导致界面滑动和界面内按钮点击事件相冲突。

由于采用了ViewGroup来管理子view,只适合于页面数较少而且较固定的情况,因为viewgroup需要一开始就调用addView,把所有view都加进去并layout,太多页面会有内存问题。如果是页面很多,而且随时动态增长的话,就需要考虑对view做cache和动态创建,动态layout,具体做法参考下面的方法二;

 

2、从AdapterView继承,参考Android自带ListView的实现,实现子view动态创建和cache,滑动效果等。源码如下:

import android.content.Context;

import android.util.AttributeSet;

import android.util.Log;

import android.util.SparseArray;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.View;

import android.view.ViewConfiguration;

import android.view.ViewGroup;

import android.widget.AdapterView;

import android.widget.BaseAdapter;

import android.widget.Gallery;

import android.widget.Scroller;

 

/**

* 自定义一个横向滚动的AdapterView,类似与全屏的Gallery,但是一次只滚动一屏,而且每一屏支持子view的点击处理

* @author weibinke

*

*/

public class MultiPageSwitcher extends AdapterView<BaseAdapter> {

 

private BaseAdapter mAdapter = null;

private Scroller mScroller;

private int mTouchSlop;

private float mTouchStartX;

private float mLastMotionX;

private final static String TAG = “MultiPageSwitcher”;

 

private int mLastScrolledOffset = 0;

 

/** User is not touching the list */

private static final int TOUCH_STATE_RESTING = 0;

 

/** User is scrolling the list */

private static final int TOUCH_STATE_SCROLL = 2;

 

private int mTouchState = TOUCH_STATE_RESTING;

private int mHeightMeasureSpec;

private int mWidthMeasureSpec;

private int mSelectedPosition;

private int mFirstPosition;                                //第一个可见view的position

private int mCurrentSelectedPosition;

 

private VelocityTracker mVelocityTracker;

private static final int SNAP_VELOCITY = 600;

 

protected RecycleBin mRecycler = new RecycleBin();

 

private OnPostionChangeListener mOnPostionChangeListener = null;

 

public MultiPageSwitcher(Context context, AttributeSet attrs) {

super(context, attrs);

mScroller = new Scroller(context);

mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

}

 

@Override

protected void onLayout(boolean changed, int left, int top, int right,

int bottom) {

// TODO Auto-generated method stub

MLog.d(“MultiPageSwitcher.onlayout start”);

super.onLayout(changed, left, top, right, bottom);

 

if (mAdapter == null) {

return ;

}

 

recycleAllViews();

detachAllViewsFromParent();

mRecycler.clear();

 

fillAllViews();

 

MLog.d(“MultiPageSwitcher.onlayout end”);

}

 

/**

* 从当前可见的view向左边填充

*/

private void fillToGalleryLeft() {

int itemSpacing = 0;

int galleryLeft = 0;

// Set state for initial iteration

View prevIterationView = getChildAt(0);

int curPosition;

int curRightEdge;

if (prevIterationView != null) {

curPosition = mFirstPosition – 1;

curRightEdge = prevIterationView.getLeft() – itemSpacing;

} else {

// No children available!

curPosition = 0;

curRightEdge = getRight() – getLeft();

}

while (curRightEdge > galleryLeft && curPosition >= 0) {

prevIterationView = makeAndAddView(curPosition, curPosition – mSelectedPosition,

curRightEdge, false);

 

// Remember some state

mFirstPosition = curPosition;

// Set state for next iteration

curRightEdge = prevIterationView.getLeft() – itemSpacing;

curPosition–;

}

}

private void fillToGalleryRight() {

int itemSpacing = 0;

int galleryRight = getRight() – getLeft();

int numChildren = getChildCount();

int numItems = mAdapter.getCount();

// Set state for initial iteration

View prevIterationView = getChildAt(numChildren – 1);

int curPosition;

int curLeftEdge;

if (prevIterationView != null) {

curPosition = mFirstPosition + numChildren;

curLeftEdge = prevIterationView.getRight() + itemSpacing;

} else {

mFirstPosition = curPosition = numItems – 1;

curLeftEdge = 0;

}

while (curLeftEdge < galleryRight && curPosition < numItems) {

prevIterationView = makeAndAddView(curPosition, curPosition – mSelectedPosition,

curLeftEdge, true);

 

// Set state for next iteration

curLeftEdge = prevIterationView.getRight() + itemSpacing;

curPosition++;

}

}

 

/**

*填充view

*/

private void fillAllViews(){

//先创建第一个view,使其居中显示

if (mSelectedPosition >= mAdapter.getCount()&& mSelectedPosition > 0) {

//处理被记录被删除导致当前选中位置超出记录数的情况

mSelectedPosition = mAdapter.getCount() – 1;

if(mOnPostionChangeListener != null){

mCurrentSelectedPosition = mSelectedPosition;

mOnPostionChangeListener.onPostionChange(this, mCurrentSelectedPosition);

}

}

 

mFirstPosition = mSelectedPosition;

mCurrentSelectedPosition = mSelectedPosition;

 

View child = makeAndAddView(mSelectedPosition, 0, 0, true);

 

int offset = getWidth() / 2 – (child.getLeft() + child.getWidth() / 2);

child.offsetLeftAndRight(offset);

 

fillToGalleryLeft();

fillToGalleryRight();

 

}

 

/**

* Obtain a view, either by pulling an existing view from the recycler or by

* getting a new one from the adapter. If we are animating, make sure there

* is enough information in the view’s layout parameters to animate from the

* old to new positions.

*

* @param position Position in the gallery for the view to obtain

* @param offset Offset from the selected position

* @param x X-coordintate indicating where this view should be placed. This

*        will either be the left or right edge of the view, depending on

*        the fromLeft paramter

* @param fromLeft Are we posiitoning views based on the left edge? (i.e.,

*        building from left to right)?

* @return A view that has been added to the gallery

*/

private View makeAndAddView(int position, int offset, int x,

boolean fromLeft) {

 

View child;

 

//        child = mRecycler.get(position);

//        if (child != null) {

//            // Position the view

//            setUpChild(child, offset, x, fromLeft);

//

//            return child;

//        }

//

//        // Nothing found in the recycler — ask the adapter for a view

child = mAdapter.getView(position, null, this);

 

// Position the view

setUpChild(child, offset, x, fromLeft);

 

return child;

}

@Override

protected ViewGroup.LayoutParams generateDefaultLayoutParams() {

/*

* Gallery expects Gallery.LayoutParams.

*/

return new Gallery.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,

ViewGroup.LayoutParams.WRAP_CONTENT);

}

 

/**

* Helper for makeAndAddView to set the position of a view and fill out its

* layout paramters.

*

* @param child The view to position

* @param offset Offset from the selected position

* @param x X-coordintate indicating where this view should be placed. This

*        will either be the left or right edge of the view, depending on

*        the fromLeft paramter

* @param fromLeft Are we posiitoning views based on the left edge? (i.e.,

*        building from left to right)?

*/

private void setUpChild(View child, int offset, int x, boolean fromLeft) {

 

// Respect layout params that are already in the view. Otherwise

// make some up…

Gallery.LayoutParams lp = (Gallery.LayoutParams)

child.getLayoutParams();

if (lp == null) {

lp = (Gallery.LayoutParams) generateDefaultLayoutParams();

}

 

addViewInLayout(child, fromLeft ? -1 : 0, lp);

 

child.setSelected(offset == 0);

 

// Get measure specs

int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,

0, lp.height);

int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,

0, lp.width);

 

// Measure child

child.measure(childWidthSpec, childHeightSpec);

 

int childLeft;

int childRight;

 

// Position vertically based on gravity setting

int childTop = 0;

int childBottom = childTop + child.getMeasuredHeight();

 

int width = child.getMeasuredWidth();

if (fromLeft) {

childLeft = x;

childRight = childLeft + width;

} else {

childLeft = x – width;

childRight = x;

}

 

child.layout(childLeft, childTop, childRight, childBottom);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// TODO Auto-generated method stub

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mWidthMeasureSpec = widthMeasureSpec;

mHeightMeasureSpec = heightMeasureSpec;

}

 

@Override

public int getCount() {

// TODO Auto-generated method stub

return mAdapter.getCount();

}

 

@Override

public BaseAdapter getAdapter() {

// TODO Auto-generated method stub

return mAdapter;

}

 

@Override

public void setAdapter(BaseAdapter adapter) {

// TODO Auto-generated method stub

mAdapter = adapter;

 

removeAllViewsInLayout();

 

requestLayout();

}

 

@Override

public View getSelectedView() {

// TODO Auto-generated method stub

return null;

}

 

@Override

public void setSelection(int position) {

// TODO Auto-generated method stub

}

 

@Override

public boolean onInterceptTouchEvent(MotionEvent event) {

if (!mScroller.isFinished()) {

return true;

}

 

final int action = event.getAction();

MLog.d(“onInterceptTouchEvent action = “+event.getAction());

 

if (MotionEvent.ACTION_DOWN == action) {

startTouch(event);

 

return false;

}else if (MotionEvent.ACTION_MOVE == action) {

return startScrollIfNeeded(event);

}else if (MotionEvent.ACTION_UP == action || MotionEvent.ACTION_CANCEL == action) {

mTouchState = TOUCH_STATE_RESTING;

 

return false;

}

return false;

}

 

@Override

public boolean onTouchEvent(MotionEvent event) {

 

if (!mScroller.isFinished()) {

return true;

}

 

if (mVelocityTracker == null) {

mVelocityTracker = VelocityTracker.obtain();

}

 

mVelocityTracker.addMovement(event);

 

MLog.d(“onTouchEvent action = “+event.getAction());

final int action = event.getAction();

final float x = event.getX();

 

if (MotionEvent.ACTION_DOWN == action) {

startTouch(event);

 

}else if (MotionEvent.ACTION_MOVE == action) {

if (mTouchState == TOUCH_STATE_RESTING) {

startScrollIfNeeded(event);

}else if (mTouchState == TOUCH_STATE_SCROLL) {

int deltaX = (int)(x – mLastMotionX);

mLastMotionX = x;

 

scrollDeltaX(deltaX);

 

}

}else if (MotionEvent.ACTION_UP == action || MotionEvent.ACTION_CANCEL == action) {

if (mTouchState == TOUCH_STATE_SCROLL) {

onUp(event);

}

}

return true;

}

 

 

private void scrollDeltaX(int deltaX){

 

//先把现有的view坐标移动

for (int i = 0; i < getChildCount(); i++) {

getChildAt(i).offsetLeftAndRight(deltaX);

}

 

boolean toLeft = (deltaX < 0);

detachOffScreenChildren(toLeft);

 

if (deltaX < 0) {

//sroll to right

fillToGalleryRight();

}else {

fillToGalleryLeft();

}

 

invalidate();

 

int position = calculteCenterItem() + mFirstPosition;

if (mCurrentSelectedPosition != position) {

mCurrentSelectedPosition = position;

if (mOnPostionChangeListener != null) {

mOnPostionChangeListener.onPostionChange(this, mCurrentSelectedPosition);

}

}

}

 

private void onUp(MotionEvent event){

 

 

final VelocityTracker velocityTracker = mVelocityTracker;

velocityTracker.computeCurrentVelocity(1000);

int velocityX = (int) velocityTracker.getXVelocity();

 

MLog.d( “onUp velocityX:”+velocityX);

 

if (velocityX < -SNAP_VELOCITY && mSelectedPosition < mAdapter.getCount() – 1) {

if (scrollToChild(mSelectedPosition + 1)) {

mSelectedPosition ++;

}

}else if (velocityX > SNAP_VELOCITY && mSelectedPosition > 0) {

if (scrollToChild(mSelectedPosition – 1)) {

mSelectedPosition –;

}

}else{

int position = calculteCenterItem();

int newpostion = mFirstPosition + position;

if (scrollToChild(newpostion)) {

mSelectedPosition = newpostion;

}

}

 

if (mVelocityTracker != null) {

mVelocityTracker.recycle();

mVelocityTracker = null;

}

 

mTouchState = TOUCH_STATE_RESTING;

}

 

/**

* 计算最接近中心点的view

* @return

*/

private int calculteCenterItem(){

View child = null;

int lastpostion = 0;

int lastclosestDistance = 0;

int viewCenter = getLeft() + getWidth() / 2;

for (int i = 0; i < getChildCount(); i++) {

child = getChildAt(i);

if (child.getLeft() < viewCenter && child.getRight() > viewCenter ) {

lastpostion = i;

break;

}else {

int childClosestDistance = Math.min(Math.abs(child.getLeft() – viewCenter), Math.abs(child.getRight() – viewCenter));

if (childClosestDistance < lastclosestDistance) {

lastclosestDistance = childClosestDistance;

lastpostion = i;

}

}

}

 

return lastpostion;

}

 

public void moveNext(){

if (!mScroller.isFinished()) {

return;

}

 

if (0 <= mSelectedPosition && mSelectedPosition < mAdapter.getCount() – 1) {

if (scrollToChild(mSelectedPosition + 1)) {

mSelectedPosition ++;

}else {

makeAndAddView(mSelectedPosition + 1, 1, getWidth(), true);

if (scrollToChild(mSelectedPosition + 1)) {

mSelectedPosition ++;

}

}

}

}

 

public void movePrevious(){

if (!mScroller.isFinished()) {

return;

}

 

if (0 < mSelectedPosition && mSelectedPosition < mAdapter.getCount()) {

if (scrollToChild(mSelectedPosition -1)) {

mSelectedPosition –;

}else {

makeAndAddView(mSelectedPosition – 1, -1, 0, false);

mFirstPosition = mSelectedPosition – 1;

if (scrollToChild(mSelectedPosition – 1)) {

mSelectedPosition –;

}

}

}

}

 

private boolean scrollToChild(int position){

MLog.d( “scrollToChild positionm,FirstPosition,childcount:”+position + “,” + mFirstPosition+ “,” + getChildCount());

View child = getChildAt(position – mFirstPosition );

if (child != null) {

int distance = getWidth() / 2 – (child.getLeft() + child.getWidth() / 2);

 

mLastScrolledOffset = 0;

mScroller.startScroll(0, 0, distance, 0,200);

invalidate();

 

return true;

}

 

MLog.d( “scrollToChild some error happened”);

 

 

return false;

}

 

@Override

public void computeScroll() {

// TODO Auto-generated method stub

if (mScroller.computeScrollOffset()) {

int scrollX = mScroller.getCurrX();

//                        Mlog.d(“MuticomputeScroll ,” + scrollX);

 

scrollDeltaX(scrollX – mLastScrolledOffset);

mLastScrolledOffset = scrollX;

postInvalidate();

}

}

 

private void startTouch(MotionEvent event){

mTouchStartX = event.getX();

 

mTouchState = mScroller.isFinished()? TOUCH_STATE_RESTING : TOUCH_STATE_SCROLL;

 

mLastMotionX = mTouchStartX;

}

 

private boolean startScrollIfNeeded(MotionEvent event){

final int xPos = (int)event.getX();

mLastMotionX = event.getX();

if (xPos < mTouchStartX – mTouchSlop

|| xPos > mTouchStartX + mTouchSlop

) {

// we’ve moved far enough for this to be a scroll

mTouchState = TOUCH_STATE_SCROLL;

return true;

}

return false;

}

 

/**

* Detaches children that are off the screen (i.e.: Gallery bounds).

*

* @param toLeft Whether to detach children to the left of the Gallery, or

*            to the right.

*/

private void detachOffScreenChildren(boolean toLeft) {

int numChildren = getChildCount();

int start = 0;

int count = 0;

int firstPosition = mFirstPosition;

if (toLeft) {

final int galleryLeft = 0;

for (int i = 0; i < numChildren; i++) {

final View child = getChildAt(i);

if (child.getRight() >= galleryLeft) {

break;

} else {

count++;

mRecycler.put(firstPosition + i, child);

}

}

} else {

final int galleryRight = getWidth();

for (int i = numChildren – 1; i >= 0; i–) {

final View child = getChildAt(i);

if (child.getLeft() <= galleryRight) {

break;

} else {

start = i;

count++;

mRecycler.put(firstPosition + i, child);

}

}

}

 

detachViewsFromParent(start, count);

if (toLeft) {

mFirstPosition += count;

}

mRecycler.clear();

}

public void setOnPositionChangeListen(OnPostionChangeListener onPostionChangeListener){

mOnPostionChangeListener = onPostionChangeListener;

}

public int getCurrentSelectedPosition(){

return mCurrentSelectedPosition;

}

/**

* 刷新数据,本来想用AdapterView.AdapterDataSetObserver机制来实现的,但是整个逻辑移植比较麻烦,就暂时用这个替代了

*/

public void updateData(){

requestLayout();

}

private void recycleAllViews() {

int childCount = getChildCount();

final RecycleBin recycleBin = mRecycler;

 

// All views go in recycler

for (int i=0; i<childCount; i++) {

View v = getChildAt(i);

int index = mFirstPosition + i;

recycleBin.put(index, v);

}

}

class RecycleBin {

private SparseArray<View> mScrapHeap = new SparseArray<View>();

 

public void put(int position, View v) {

if (mScrapHeap.get(position) != null) {

Log.e(TAG,”RecycleBin put error.”);

}

mScrapHeap.put(position, v);

}

View get(int position) {

// System.out.print(“Looking for ” + position);

View result = mScrapHeap.get(position);

if (result != null) {

MLog.d(“RecycleBin get hit.”);

mScrapHeap.delete(position);

} else {

MLog.d(“RecycleBin get Miss.”);

}

return result;

}

View peek(int position) {

// System.out.print(“Looking for ” + position);

return mScrapHeap.get(position);

}

void clear() {

final SparseArray<View> scrapHeap = mScrapHeap;

final int count = scrapHeap.size();

for (int i = 0; i < count; i++) {

final View view = scrapHeap.valueAt(i);

if (view != null) {

removeDetachedView(view, true);

}

}

scrapHeap.clear();

}

}

public interface OnPostionChangeListener{

abstract public void onPostionChange(View v,int position);

}

}

通过admin

Android实现欢迎界面滑动效果

Android应用大部分都会有欢迎界面,几张whatsnew图片可以左右滑动,这里贴下自己的源码。大概思路是:重写Gallery,重写onFling()。

为什么不直接用Gallery呢?因为galler默认会有滑动惯性,会出现一次滑动几页的现象,这里明显不合适。

另外,这种方式会有一个小问题,如果你的界面里带了某些控件,而且设置了OnClickListener(),那么用户如果从控件所在区域开始拖动,是不会有拖动效果的,具体原因是onTouchEvent和onInterceptTouchEvent的传递问题。如果想要解决这个问题,可以看下一篇文章,通过重写AdapterView来实现多页滑动效果。

 

 

贴下代码:

import android.content.Context;

import android.util.AttributeSet;

import android.view.KeyEvent;

import android.view.MotionEvent;

import android.view.ViewConfiguration;

import android.widget.Gallery;

public class SingleScrollGallery extends Gallery {

private static final int TOUCH_STATE_REST = 0;

private static final int TOUCH_STATE_SCROLLING = 1;

private int mTouchState = TOUCH_STATE_REST;

private int mTouchSlop;

private float mLastMotionX;

private float mLastMotionY;

 

public SingleScrollGallery(Context context ,AttributeSet attrSet) {

super(context,attrSet);

// TODO Auto-generated constructor stub

mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

}

 

@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

float velocityY) {

// TODO Auto-generated method stub

//          return super.onFling(e1, e2, velocityX, velocityY);//方法一:只去除翻页惯性

//  return false;//方法二:只去除翻页惯性  注:没有被注释掉的代码实现了开始说的2种效果。

int kEvent;

if(isScrollingLeft(e1, e2)){

//Check if scrolling left

kEvent = KeyEvent.KEYCODE_DPAD_LEFT;

}  else{

//Otherwise scrolling right

kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;

}

onKeyDown(kEvent, null);

return true;

}

 

private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2)

{

return e2.getX() > e1.getX();

}

 

@Override

public boolean onTouchEvent(MotionEvent event) {

// TODO Auto-generated method stub

return super.onTouchEvent(event);

}

 

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

final int action = ev.getAction();

if ((action == MotionEvent.ACTION_MOVE) &&

(mTouchState != TOUCH_STATE_REST)) {

return true;

}

 

final float x = ev.getX();

final float y = ev.getY();

 

switch (action) {

case MotionEvent.ACTION_MOVE:

final int xDiff = (int)Math.abs(mLastMotionX-x);

if (xDiff>0) {

mTouchState = TOUCH_STATE_SCROLLING;

}

break;

 

case MotionEvent.ACTION_DOWN:

mLastMotionX = x;

mLastMotionY = y;

mTouchState = TOUCH_STATE_REST;

break;

 

case MotionEvent.ACTION_CANCEL:

case MotionEvent.ACTION_UP:

mTouchState = TOUCH_STATE_REST;

break;

}

 

return mTouchState != TOUCH_STATE_REST;

}

}

通过admin

Manifest.xml中不要出现重复的uses-permission声明

虽然Android没有明确指定uses-permission不可以重复写,但是最近的经验是最好是不要重复,否则在某些厂商定制的技巧可能出现问题。

 

最近写一个应用,里面有用到网络访问,发现在有些机型下总是访问不了网络。而其他机型都是可以的。出现问题的手机网络都是正常的。

后面发现Manifest.xml中有好几个网络相关的uses-permission都重复写了几个,于是把重复的去掉之后,发现现在访问网络都正常了。

通过admin

android隐藏以及显示软键盘以及不自动弹出键盘的方法

1、//隐藏软键盘

((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(WidgetSearchActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

2、//显示软键盘,控件ID可以是EditText,TextView

((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).showSoftInput(控件ID, 0);

 

3、不自动弹出键盘:

带有EditText控件的在第一次显示的时候会自动获得focus,并弹出键盘,如果不想自动弹出键盘,有两种方法:

方法一:在mainfest文件中把对应的activity设置

android:windowSoftInputMode=”stateHidden” 或者android:windowSoftInputMode=”stateUnchanged”。

方法二:可以在布局中放一个隐藏的TextView,然后在onCreate的时候requsetFocus。

注意TextView不要设置Visiable=gone,否则会失效

,可以在布局中放一个隐藏的TextView,然后在onCreate的时候requsetFocus。

注意TextView不要设置Visiable=gone,否则会失效

<TextView

android:id=”@+id/text_notuse”

android:layout_width=”wrap_content”

android:layout_height=”wrap_content”

android:focusable=”true”

android:focusableInTouchMode=”true”

/>

 

TextView textView = (TextView)findViewById(R.id.text_notuse);

textView.requestFocus();