读《50 Android Hacks》笔记整理Hack 9~Hack 17
2015-11-29 08:43
661 查看
第三章 使用视图的技巧和窍门
Hack 9 避免在EditText中验证日期
Hack 10 格式化TextView的文本
Hack 11 为文本添加发亮的效果
Hack 12 为背景添加圆角边框
Hack 13 在onCreate方法中获取View的宽度和高度
Hack 14 VideoView的转屏处理技巧
Hack 15 移除背景以提升Activity的启动速度
Hack 16 更改Toast显示位置的技巧
Hack 17 使用Gallery创建向导表单
方法:直接在xml中进行设置,为Button添加android:background属性,值为:@android:drawable/edit_text。
我们在这里直接使用了Android内置资源,但也是有利有弊的:
利:可以使应用程序更好的适应不同设备。
弊:因为系统的版本不同,所以会导致应用程序在不同设备上的用户体验也不同。
在这里我们最好不要直接把监听事件设置在EditText上。
外链地址1
外链地址2
示例:使用TextView添加不同样式的文本和链接。
首先,添加超链接,可以通过Html.fromHtml()方法设置TextView的文本内容。代码如下:
该方法将HTML转化为一个Spanned对象,并以此为参数调用TextView的setText()方法。
文本显示不同style,这里是使用SpannableString类(它是Spanned的子类)创建一个Spanned对象。代码如下:
我们这里通过文本中字符的索引指定不同的跨度(span),不同的跨度将文本内容分成不同的部分,然后通过SpannableString就可以为不同的部分指定不同的样式。
外链地址1
外链地址——Spanned
因为我们需要的字体样式不同,所以首先需要创建一个继承子TextView的类,然后设置需要的字体。代码如下:
当创建对象时,我们从assets文件夹中获取字体信息,然后在1进行设置该字体,这样便拥有一个可以使用自定义字体显示文本内容的UI控件。
实现思路:我们可以通过两个TextView实现,第一个TextView是背景中显示88:88:88的阴影,第二个TextView用于显示当前时间。这样就可以达到模拟数字时钟的重影效果。
为了实现发光效果,TextView提供了一个方法:
也可以直接通过XML中的android:shadowColor,android:shadowDx,android:shadowDy和android:shadowRadius属性来达到这种效果。代码如下:
这里还可以使用android:alpha属性指定透明度。修改shadowDx和shadowDy的值可以改变阴影与文本之间的偏移。这里为了产生一种发亮效果,我们把shadowDx和shadowDy设置为0。
外链地址1
外链地址2
由上文可知,我们并没有使用任何特殊属性,只是为背景属性指定了drawable值,但这个值不是一个图片,而是一个XML文件。在drawable值指定的XML文件中有一个ShapeDrawable对象,该对象是一个可绘制对象,可以用来绘制各种原始形状,如方块等。ShapeDrawable对应的XML文件如下:
ShapeDrawable是一个为UI控件添加特效的好工具。
外链地址1
为什么呢?
因为当onCreate()方法被调用时,会通过LayoutInflater将XML布局文件填充到ContentView。填充过程只包括创建视图,却不包括设置其大小。
视图的大小是何时指定的呢?
开发文档解释如下:
“绘制布局由两个遍历过程组成:测量过程和布局过程。测量过程由measure(int,int)方法完成,该方法从上到下遍历视图树。在递归遍历过程中,每个视图都会向下层传递尺寸和规格。当measure方法遍历结束时,每个视图都保存了各自的尺寸信息。第二个过程由layout(int,int,int,int)方法完成,该方法也是由上而下遍历视图树,在遍历过程中,每个父视图通过测量过程的结果定位所有子视图的位置信息。“
所以,结论:只有在整个布局绘制完成后,视图才能得到自身的高和宽,这个过程发生在onCreate()方法之后。因此,在此之前调用getHeight()和getWidth()方法返回的结果都是0。
那怎么才能得到控件的宽和高呢?
开发者可以使用View的post()方法解决上述问题。该方法接收一个Runnable线程参数,并将其添加到消息队列中。有趣的是Runnable线程会在UI线程中执行。使用post()方法代码如下:
外链地址1
外链地址2
代码如下:
外链地址1
我们在创建一个项目运行后使用HierarchyViewer工具检测可以发现会有两个节点,一个是标题栏的一个是我们的界面。如果我们不用标题栏可以把它隐藏,这个就可以减少一个节点。隐藏标题栏方法
我们发现在界面节点中还有一个FrameLayout这个又是什么呢?
FrameLayout是在执行setContentView()方法时创建的。默认情况下,框架层会以默认背景色填充窗口,而FrameLayout这个就是用于绘制默认背景色的。所以如果使用不透明界面或自定义背景,那么绘制默认背景色就完全是浪费时间。所以就可以移除这个,代码如下:
主题可以在标签中设置,也可以在标签中设置。
外链地址1
外链地址2
外链地址1
使用Gallery控件创建向导表单可以简化用户填写较长表单多流程。将表单项放在不同页面中,并且利用Gallery控件的默认动画添加悦目的效果,可以使用户在填写表单的过程中更愉悦些。
根据需求也可以使用ViewPage开发类似功能,只是其Adapter返回的不是View而是Fragment。因为这个现在使用的不是很多,所以就不详细描述,具体使用请参照外链地址。
外链地址1
Hack 9 避免在EditText中验证日期
Hack 10 格式化TextView的文本
Hack 11 为文本添加发亮的效果
Hack 12 为背景添加圆角边框
Hack 13 在onCreate方法中获取View的宽度和高度
Hack 14 VideoView的转屏处理技巧
Hack 15 移除背景以提升Activity的启动速度
Hack 16 更改Toast显示位置的技巧
Hack 17 使用Gallery创建向导表单
第三章 使用视图的技巧和窍门
Hack 9 避免在EditText中验证日期
思路:把Button控件默认背景修改为EditText的背景。方法:直接在xml中进行设置,为Button添加android:background属性,值为:@android:drawable/edit_text。
我们在这里直接使用了Android内置资源,但也是有利有弊的:
利:可以使应用程序更好的适应不同设备。
弊:因为系统的版本不同,所以会导致应用程序在不同设备上的用户体验也不同。
在这里我们最好不要直接把监听事件设置在EditText上。
外链地址1
外链地址2
Hack 10 格式化TextView的文本
我们会注意到在一个应用程序里有的时候在一个文本中会出现不同的样式,我们第一个想法可能是这个是一个自定义视图,其实这个UI控件是用TextView实现的。示例:使用TextView添加不同样式的文本和链接。
首先,添加超链接,可以通过Html.fromHtml()方法设置TextView的文本内容。代码如下:
mTextView1 = (TextView)findViewById(R.id.my_text_view_html); String text = "Visit<a href=\"http://manning.com/\">Manning home page</a>"; mTextView1.setText(Html.fromHtml(text)); mTextView1.setMovementMethod(LinkMovementMethod.getInstance());
该方法将HTML转化为一个Spanned对象,并以此为参数调用TextView的setText()方法。
文本显示不同style,这里是使用SpannableString类(它是Spanned的子类)创建一个Spanned对象。代码如下:
mTextView2 = (TextView)findViewById(R.id.my_text_view_spannable); Spannable sText = new SpannableString(mTextView2.getText()); sText.setSpan(new BackgroundColorSpan(Color.RED),1,4,0); sText.setSpan(new ForegroundColorSpan(Color.BLUE),5,9,0); mTextView2.setText(sText);
我们这里通过文本中字符的索引指定不同的跨度(span),不同的跨度将文本内容分成不同的部分,然后通过SpannableString就可以为不同的部分指定不同的样式。
外链地址1
外链地址——Spanned
Hack 11 为文本添加发亮的效果
示例:显示一个高亮绿灯的数字时钟因为我们需要的字体样式不同,所以首先需要创建一个继承子TextView的类,然后设置需要的字体。代码如下:
public class LedTextView extends TextView{ public LedTextView(Context context,AttributeSet attrs){ super(context,attrs); AssetManager assets = context.getAssets(); //1.设置字体,这里是为了设置与数字时钟对应的字体,如果只是要发亮效果可以不创建这个类 final Typeface font = Typeface.createFromAsset(assets,FONT_DIGITAL_7); setTypeface(font); } }
当创建对象时,我们从assets文件夹中获取字体信息,然后在1进行设置该字体,这样便拥有一个可以使用自定义字体显示文本内容的UI控件。
实现思路:我们可以通过两个TextView实现,第一个TextView是背景中显示88:88:88的阴影,第二个TextView用于显示当前时间。这样就可以达到模拟数字时钟的重影效果。
为了实现发光效果,TextView提供了一个方法:
public void setShadowLayer(float radius,float dx,float dy,int color)
也可以直接通过XML中的android:shadowColor,android:shadowDx,android:shadowDy和android:shadowRadius属性来达到这种效果。代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 这里设置较浅的颜色,以便使文本看起来透明些 --> <com.manning.androidhacks.hack011.view.LedTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="88:88:88" android:textSize="80sp" android:textColor="3300ff00"/> <!-- 这里设置文本和阴影颜色相同,使用shadowRadius改变阴影半径可以使其看起来更亮 --> <com.manning.androidhacks.hack011.view.LedTextView android:id="@+id/main_clock_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="08:43:02" android:textSize="80sp" android:textColor="#00ff00" android:shadowColor-"#00ff00" android:shadowDx="0" android:shadowDy="0" android:shadowRadius="10"/> </RelativeLayout>
这里还可以使用android:alpha属性指定透明度。修改shadowDx和shadowDy的值可以改变阴影与文本之间的偏移。这里为了产生一种发亮效果,我们把shadowDx和shadowDy设置为0。
外链地址1
外链地址2
Hack 12 为背景添加圆角边框
达到这种效果可以直接在XML中设置背景。代码如下:<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello" android:textColor="#000000" android:padding="10dp" android:background="@drawable/button_rounded_background"/>
由上文可知,我们并没有使用任何特殊属性,只是为背景属性指定了drawable值,但这个值不是一个图片,而是一个XML文件。在drawable值指定的XML文件中有一个ShapeDrawable对象,该对象是一个可绘制对象,可以用来绘制各种原始形状,如方块等。ShapeDrawable对应的XML文件如下:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#aaaaaa" /> <!-- 将边框指定为圆角 --> <corners android:radius="15dp"/> </shape>
ShapeDrawable是一个为UI控件添加特效的好工具。
外链地址1
Hack 13 在onCreate()方法中获取View的宽度和高度
开发者可能会用到View的getHeight()和getWidth()方法。但使用的时候这里有个小陷阱:如果试图在Activity的onCreate()方法中获取控件的宽和高,在onCreate()方法中调用上述方法,会发现返回值是0。为什么呢?
因为当onCreate()方法被调用时,会通过LayoutInflater将XML布局文件填充到ContentView。填充过程只包括创建视图,却不包括设置其大小。
视图的大小是何时指定的呢?
开发文档解释如下:
“绘制布局由两个遍历过程组成:测量过程和布局过程。测量过程由measure(int,int)方法完成,该方法从上到下遍历视图树。在递归遍历过程中,每个视图都会向下层传递尺寸和规格。当measure方法遍历结束时,每个视图都保存了各自的尺寸信息。第二个过程由layout(int,int,int,int)方法完成,该方法也是由上而下遍历视图树,在遍历过程中,每个父视图通过测量过程的结果定位所有子视图的位置信息。“
所以,结论:只有在整个布局绘制完成后,视图才能得到自身的高和宽,这个过程发生在onCreate()方法之后。因此,在此之前调用getHeight()和getWidth()方法返回的结果都是0。
那怎么才能得到控件的宽和高呢?
开发者可以使用View的post()方法解决上述问题。该方法接收一个Runnable线程参数,并将其添加到消息队列中。有趣的是Runnable线程会在UI线程中执行。使用post()方法代码如下:
protected void onCreate(){ super.onCreate(savedInstanceState); setContentView(R.layout.main); View veiw = findViewById(R.id.main_my_view); //布局绘制后获取View的大小 view.post(new Runnable(){ @Override public void run(){ //得到正确的宽和高 Log.d(TAG,"view has width:"+view.getWidth()+"and height:"+view.getHeight()); } }); }
外链地址1
外链地址2
Hack 14 VideoView的转屏处理技巧
这个其实就是根据判断屏幕当前横竖屏来设置videoView的宽高。代码如下:
private void setVideoViewPosition(){ //1.判断当前横竖屏配置 if(getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){ //2.使mPortraitContent可视 mPortraitContent.setVisibility(View.VISIBLE); //3.videoView的位置 int[] locationArray = new int[2]; mPortraitPosition.getLocationOnScreen(locationArray); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mPortraitPosition.getWidth(),mPortraitPosition.getHeight()); params.leftMargin = locationArray[0]; params.topMargin = locationArray[1]; //4.设置videoView的布局参数 mVideoView.setLayoutParams(params); }else{ //5.隐藏mPortraitContent mPortraitContent.setVisibility(View.GONE); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT); params.addRule(RelativeLayout.CENTER_IN_PARENT); //6.设置videoView的布局参数 mVideoView.setLayoutParams(params); } }
外链地址1
Hack 15 移除背景以提升Activity的启动速度
Android SDK中提供了HierarchyViewer工具,该工具可以用来检测未被使用的视图以减少视图树的层次。这个HierarchyViewer可以查看外链地址1。我们在创建一个项目运行后使用HierarchyViewer工具检测可以发现会有两个节点,一个是标题栏的一个是我们的界面。如果我们不用标题栏可以把它隐藏,这个就可以减少一个节点。隐藏标题栏方法
我们发现在界面节点中还有一个FrameLayout这个又是什么呢?
FrameLayout是在执行setContentView()方法时创建的。默认情况下,框架层会以默认背景色填充窗口,而FrameLayout这个就是用于绘制默认背景色的。所以如果使用不透明界面或自定义背景,那么绘制默认背景色就完全是浪费时间。所以就可以移除这个,代码如下:
<resources> <style name="Theme.NoBackground" parent="android:Theme"> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@null</item> </style> </resources>
主题可以在标签中设置,也可以在标签中设置。
外链地址1
外链地址2
Hack 16 更改Toast显示位置的技巧
设置方法://创建Toast Toast toast = Toast.makeText(this,"Bottom Right!",Toast.LENGTH_SHORT); //设置gravity属性,以改变默认位置 toast.setGravity(Gravity.BOTTOM|Gravity.RIGHT,0,0); toast.show();
外链地址1
Hack 17 使用Gallery创建向导表单
向导表单就是可以把表单项分割到不同的视图中。为了让表单具备弹出窗口的样式,Activity使用Theme.Dialog样式。在该Activity中,我吗会创建一个Gallery对象,并用一个Adapter填充这个Gallery,因为该Adapter需要与Activity交互,因此我们使用Delegate委托接口。使用Gallery控件创建向导表单可以简化用户填写较长表单多流程。将表单项放在不同页面中,并且利用Gallery控件的默认动画添加悦目的效果,可以使用户在填写表单的过程中更愉悦些。
根据需求也可以使用ViewPage开发类似功能,只是其Adapter返回的不是View而是Fragment。因为这个现在使用的不是很多,所以就不详细描述,具体使用请参照外链地址。
外链地址1
相关文章推荐
- Android通过session与服务端保持一致
- Android TextView
- Draw 9-patch(点9图)
- material design
- Android之集成友盟推送功能
- Android Studio——R文件小问题
- Android开发之动画(转)
- Android手机出现"已安装了存在签名冲突的同名数据包"的原因及解决办法
- Android:Style详解
- Android:drawable汇总
- Android RelativeLayout 学习
- GSON使用实践
- android 下拉刷新,上拉加载
- Android开发常用的工具类
- 精简我们的apk的方法
- Android:layer-list详解
- android应用程序中获取view的位置
- Android develop 国际化
- android添加购物车动画实现
- Android Studio的使用第一篇优化篇