标签:android style blog http color io os 使用 java
一、风格与主题
1>Style与Theme的区别
Theme是针对窗体级别的,改变窗体样式;
Style是针对窗体元素级别的,改变指定控件或者Layout的样式;
2>使用Style
【创建Style】
2.1. 在res\values\ 下创建styles.xml文件。
2.2.. 添加<resouces>节点(根节点)。
2.3. 添加自定义的style及其属性。
style的写法通常为:
<style name="MyStyle" [parent="PARENT"]>
<item name="[ATTR]">[VALUE]</>
</style>
其中,parent属性为其父style的名字(可选),通过设置该值,可继承其他style的属性。当我们需要对现有的style做微小的改变时,这个值非常实用。
[ATTR]为需要设定的属性名,如: android:textColor等
[VALUE]为其预设的值。
如我们需要将控件的文字颜色设为红色,可使用如下style:
<style name="MyStyle">
<item name="android:textColor">#FFFF0000</item>
</style>
【为控件指定Style】
在Layout中,为控件指定style属性,如:
<TextView style="@style/MyTextStyle" />
3>Theme
[ 使用方法 ]
在AndroidManifest.xml文件中,为Activity指定theme属性(推荐).
在Activity创建时调用setTheme函数 (必须在setContextView前调用 ).
[ 系统自带的Theme ]
1 Android已经为我们定义好了一些theme,需要是我们可以直接拿来使用。常用的Theme通常如下:
2 android:theme="@android:style/Theme.Dialog" 将一个Activity显示为能话框模式
3 android:theme="@android:style/Theme.NoTitleBar" 不显示应用程序标题栏
4 android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 不显示应用程序标题栏,并全屏
5 android:theme="@Theme.Light" 背景为白色
6 android:theme="Theme.Light.NoTitleBar" 白色背景并无标题栏
7 android:theme="Theme.Light.NoTitleBar.Fullscreen" 白色背景,无标题栏,全屏
8 android:theme="Theme.Black" 背景黑色
9 android:theme="Theme.Black.NoTitleBar" 黑色背景并无标题栏
10 android:theme="Theme.Black.NoTitleBar.Fullscreen" 黑色背景,无标题栏,全屏
11 android:theme="Theme.Wallpaper" 用系统桌面为应用程序背景
12 android:theme="Theme.Wallpaper.NoTitleBar" 用系统桌面为应用程序背景,且无标题栏
13 android:theme="Theme.Wallpaper.NoTitleBar.Fullscreen" 用系统桌面为应用程序背景,无标题栏,全屏
[ 定义自己的Theme ]
1 Theme的写法和style很相似,也为: 2 <style name="MyTheme" [parent="PARENT"] > 3 <item name="[ATTR]">[VALUE]</> 4 </style> 5 6 Theme的属性在Android的文档中并没有介绍,不过我们可以从系统自带的theme中对其进行了解: 7 以下我们从Anroid系统本身所带的theme.xml中提取出来的一些常用的属性: 8 9 <item name="windowBackground">@android:drawable/screen_background_dark</item> 10 <item name="windowFrame">@null</item> 11 <item name="windowNoTitle">false</item> 12 <item name="windowFullscreen">false</item> 13 <item name="windowIsFloating">false</item> 14 <item name="windowContentOverlay">@android:drawable/title_bar_shadow</item> 15 <item name="windowTitleStyle">@android:style/WindowTitle</item> 16 <item name="windowTitleSize">25dip</item> 17 <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground</item> 18 <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
4>示例
范例1:使用Style及Theme
参见sundy.android.demo.uiadv.style.StyleActivity.java
该示例展示了如何使用自定义的style及theme
范例2:气泡窗口
参见sundy.android.demo.uiadv.style.BubbleThemeActivity.java
范例3:毛玻璃效果
参见sundy.android.demo.uiadv.style.BlurThemeActivity.java
二、换肤
2.1>使用Theme进行简单的换肤
通过改变Theme,可对Activity及控件的风格进行切换,多在需要改变控件显示效果时使用。
参见sundy.android.demo.uiadv.skin.ThemeSkinActivity.java
---------------
为不同的皮肤编写Theme;
在onCreate中为Activity使用不同的Theme;
2.2>通过改变界面的布局文件进行换肤
通过改变布局文件,我们可以对整个UI有较大幅度的修改。当使用Theme无法满足换肤需求时,我们可以修改Activity使用的layout。
为不同的皮肤编写不同的布局文件;
加载布局文件;
重新绑定界面控件;
2.3>Case:横竖屏翻转主题Theme切换
三、提高UI性能
3.1>减少主线程的阻塞时间
若一个操作的耗时较长(超过5秒),我们应该将其放入后台线程中执行,只在需要修改UI界面时通知主线程进行修改。
Android已经提供了AsyncTask以实现从主线程生成新的异步任务的方法,下面我们将实现一个DownloadFilesTask,该任务将会在后台下载文件,每当有文件下载完成时,则通知主线程修改进度,全部下载完成时,将弹出对话框通知用户下载已完成。
示例:
当我们需要通过网络下载文件,同时需要我们的下载进度通知UI,我们可以使用如下代码:
1 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { 2 //在后台线程开始前执行 3 protected void onPreExecute() { 4 } 5 //后台执行函数 6 protected Long doInBackground(URL... urls) { 7 int count = urls.length; 8 long totalSize = 0; 9 for (int i = 0; i < count; i++) { 10 //下载文件,并在下载完成时通过publishProgress通知UI进行更新 11 totalSize += Downloader.downloadFile(urls[i]); 12 publishProgress((int) ((i / (float) count) * 100)); 13 } 14 return totalSize; 15 } 16 protected void onProgressUpdate(Integer... progress) { 17 setProgressPercent(progress[0]); //设置完成进度 18 } 19 //在后台线程完成后执行 20 protected void onPostExecute(Long result) { 21 showDialog("Downloaded " + result + " bytes"); //通知用户下载完成 22 } 23 }
3.2>提高Adapter&AdapterView的效率
1,优化Adapter 2, 优化AdapterView
Adapter是数据和AdapterView之间的桥梁,每当需要显示Item时,都会调用getView(),倘若我们的数据量很大,而Adapter的效率很低(如每次都会调用inflate创建新的View),结果会是怎样?
如使用以下代码(效率不好):
1 public View getView(int position, View convertView, ViewGroup parent) { 2 View item = mInflater.inflate(R.layout.list_item_icon_text, null); 3 ((TextView) item.findViewById(R.id.text)).setText(DATA[position]); 4 ((ImageView) item.findViewById(R.id.icon)).setImageBitmap( 5 (position & 1) == 1 ? mIcon1 : mIcon2); 6 return item; 7 }
【重用已生成过的Item View】
如简单的使用以下代码,效果将会得到很好的提升
1 public View getView(int position, View convertView, ViewGroup 2 parent) { 3 if (convertView == null) { 4 convertView = 5 mInflater.inflate(R.layout.item, null); 6 }else if(convertView != null) 7 ((TextView) 8 convertView.findViewById(R.id.text)).setText(DATA[position]); 9 ((ImageView) 10 convertView.findViewById(R.id.icon)).setImageBitmap( 11 (position & 1) == 1 ? mIcon1 : 12 mIcon2); 13 return convertView; 14 }
【添加ViewHolder ,避免重复查找需要修改的控件】
使用findViewById也是一个耗时的操作,我们可以使用ViewHolder进行缓冲。
这对于Item数量很大或者Item的布局很复杂的情况特别有效
1 public View getView(int position, View convertView, ViewGroup parent) { 2 ViewHolder holder; 3 if (convertView == null) { 4 convertView = mInflater.inflate(R.layout.list_item_icon_text, null); 5 holder = new ViewHolder(); 6 holder.text = (TextView) convertView.findViewById(R.id.text); 7 holder.icon = (ImageView) convertView.findViewById(R.id.icon); 8 convertView.setTag(holder); 9 } else { 10 holder = (ViewHolder) convertView.getTag(); 11 } 12 holder.text.setText(DATA[position]); 13 holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2); 14 return convertView; 15 } 16 static class ViewHolder { 17 TextView text; 18 ImageView icon; 19 }
【缓存Item的数据】
1 若获取Item中的数据需要的时间较长,我们也可以将其缓存在ViewHolder中 2 public View getView(int position, View convertView, ViewGroup parent) { 3 ViewHolder holder; 4 if (convertView == null) { 5 convertView = mInflater.inflate(R.layout.list_item_icon_text, null); 6 holder = new ViewHolder(); 7 holder.text = (TextView) convertView.findViewById(R.id.text); 8 holder.icon = (ImageView) convertView.findViewById(R.id.icon); 9 holder.data = DATA[position]; 10 holder.bitmap = (position & 1) == 1 ? mIcon1 : mIcon2; 11 12 convertView.setTag(holder); 13 } else { 14 holder = (ViewHolder) convertView.getTag(); 15 } 16 holder.text.setText(holder.data); 17 holder.icon.setImageBitmap(holder.bitmap); 18 return convertView; 19 } 20 21 static class ViewHolder { 22 TextView text; 23 ImageView icon; 24 String data; 25 Bitmap bitmap; 26 } 27 }
【分段显示】
类比传统的findByPage。
3.3>优化布局文件
【使用观察布局的工具: Hierarchy Viewer】
这是Android中提供的一个观察布局的工具:层级观察器Hierarchy viewer
Hierarchy viewer工具是一个非常好的布局优化工具,同时,你也可以通过它学习他人的布局。
Hierarchy viewer在sdk的tools目录下,打开后最新界面如图所示:
【使用布局优化工具:Layoutopt】
笨重的嵌套布局效率往往非常低下,在Android SDK中提供了一个工具可以帮助我们优化布局,以减少内存消耗,提高应用程序运行性能: Layoutopt
该工具位于SDK的tools目录下,使用方法如下:
layoutopt <directories/files to analyze>
我们可以使用示例代码中的bad_layout.xml来进行测试:
layoutopt bad_layout.xml
他将会返回结果:
11:17 This LinearLayout layout or its LinearLayout parent is useless
也就是说11至17行使用的LinearLayout或其父LinearLayout是多余的,我们完全可以去掉。
【优化布局的层次结构】
3.4>优化Activity背景图
某些时候,我们可能希望能够尽可能多的提高Activity哪怕一点点的性能,这时我们可以考虑优化Activity的背景图。
首先我们须知道,在Android的Activity中,不止有你使用SetContentView时使用的View,还包含了一些其他的View。
其根View是一个DecorView,你设置的View就被包含在其中,id为content,如下图所示:
在默认情况下,DecorView就包含了一个默认的背景图,我们接下来的优化就将以此作为出发点。
【使用getWindow().setBackgroundDrawable()】
getWindow().setBackgroundDrawable()将会改变DecorView中的背景图,从而避免不必要的绘图。
1. 若我们需要在Activity中设置一个全屏的背景图,不应该添加ImageView或在Layout中再设置背景图,而应该调用setBackgroundDrawable()去修改DecorView的背景图
2. 在不需要使用背景图时,我们应将背景图清空
【自定义主题】
1. 创建文件res/values/theme.xml
<resources>
<style name="Theme.CustomBackground" parent="android:Theme">
<item name="android:windowBackground">@null</item>
</style>
</resources>
可根据需要将windowBackground设置为null或你需要的背景图
2. 在<activity /> 或者 <application />标签中添加
android:theme="@style/Theme.CustomBackground"
3.5>使用ViewStub
ViewStub是一个看不见的,轻量级的View。它没有尺寸,也不会绘制以及以某种形式参与到布局中来。只有当调用了Inflate之后其中的View才会被实例化,这意味着用ViewStub保留View层次的结构的代价是很低的。
【延迟加载不常用的UI控件】
当某些控件只在很少的情况下才会使用,我们可以使用ViewStub来延迟加载,以提高UI加载速度及减少内存消耗。
参考 sundy.android.demo.uiadv.performance.DelayLoadActivity.java
【提高改变布局的速度】
需要的使用场景:1界面需要频繁切换. 2希望能提高切换速度。
使用方法:
1设置Activity的android:configChanges属性为keyboardHidden|orientation。
2为横竖屏分别编写不同的layout。
3创建一个layout,并包含两个ViewStub(分别对应横竖屏)。
4在横竖屏时,通过调用ViewStub.inflate()创建当前View并将另外一个设为GONE。
5绑定并设置控件的状态。
3.6>图片优化细则
控制一定范围内的缩放;
减少调色板颜色数量来控制图片大小;
四、自定义控件
4.1>什么时候使用自定义控件
在实际开发过程中,我们常会发现Android的控件无法完全满足我们的需求,而该需求在我们项目中又会经常使用,这时我们就应当使用自定义的控件。
4.2>实现自定义控件的一般步骤
(1) 选择一个和我们的需求最接近的Android控件
(2) 在XML文件中添加自定义属性(可选)
(3) 重写构造函数
(4) 通过代码或布局文件添加子控件
(5) 重载需要修改的函数
(6) 在代码或XML文件中创建控件
五、动画
5.1>分类
【Property Animation】 ViewAnimation ,ObjectAnimation。
【VIew Animation】 TweenAnimation
常用属性AnimationListener监听
渐变动画(AlphaAnimation);
旋转动画(RotateAnimation);
缩放(ScaleAnimation);
位移动画(TranslateAnimation);
【Drawable Animation】FrameAnimation
5.2>Interpolator
Interpolator定义了动画的执行过程中会如何改变。
在这里我们会介绍几个常用的变化效果,更多的效果请大家可以自己下来继续研究。
【CycleInterpolator】循环效果,该动画会循环被执行指定次数。
【AccelerateInterpolator】加速效果
【DecelerateInterpolator】减速效果
【AccelerateDecelerateInterpolator】先加速后减速的效果
5.3>总结使用方法
【创建动画】
在xml中定义
1 动画效果的定义应放在 res\anim目录下。 2 以下这两段段代码,通过在x轴连续7次的横向移动,实现了一个震动效果的动画: 3 cycle_7.xml 4 <cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="7" /> 5 6 shake.xml 7 <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0" android:toXDelta="10" android:duration="1000" android:interpolator="@anim/cycle_7" />
通过代码创建
1 Animation anim = new TranslateAnimation(0, 10, 0, 0); 2 anim.setDuration(1000); 3 anim.setInterpolator(new CycleInterpolator(7)); 4 这段代码同样实现了一个震动效果。
【为View指定动画】
通过调用View.startAnimation, 即可立即启动动画效果。
【监控动画的执行状态】
通过为动画设定AnimationListener,我们可以知道动画的执行状况:
开始、完成、重复执行。
5.4>Android动画实现原理
图形变换通过矩阵实现。图形变换是图形学中的基本知识。简单来说就是,每种变换都是一次矩阵运算。在 Android 中,Canvas 类中包含当前矩阵,当调用 Canvas.drawBitmap (bmp, x, y, Paint) 绘制时,android 会先把 bmp 做一次矩阵运算,然后将运算的结果显示在 Canvas 上。这样,编程人员只需不断修改 Canvas 的矩阵并刷新屏幕,View 里的对象就会不停的做图形变换,动画就形成了。
【动画运行模式】
独占模式:即程序主线程进入一个循环,根据动画指令不断刷新屏幕,直到动画结束。
中断模式:即有单独一个线程对时间计数,每隔一定的时间向主线程发通知,主线程接到通知后更新屏幕。
【Animation类】
每个动画都重载了父类的 applyTransformation 方法,这个方法会被父类的 getTransformation 方法调用。另外每个动画还有个 initialize 方法,完成初始化工作。
【Interpolater类】
【Transformation类】
Transformation 记录了仿射矩阵 Matrix,动画每触发一次,会对原来的矩阵做一次运算, View 的 Bitmap 与这个矩阵相乘就可实现相应的操作(旋转、平移、缩放等)。
Transformation 类封装了矩阵和 alpha 值,它有两个重要的成员,一是 mMatrix,二是 mAlpha。
【View中实现动画的过程】
view 创建动画对象,设置动画属性,调用 invalidate 刷新屏幕,启动动画;
invalidate 方法触发了 onDraw 函数;
在 onDraw 函数中:
调用动画的 getTransformation 方法,得到当前时间点的矩阵
将该矩阵设置成 Canvas 的当前矩阵
调用 canvas 的 drawBitmap 方法,绘制屏幕。
判断 getTransformation 的返回值,若为真,调用 invalidate 方法,刷新屏幕进入下一桢;若为假,说明动画完成。
5.5>为Acitivty指定动画效果
修改Activity Theme:
1 1. 在styles.xml中输入以下代码:
2 <style name="AnimationActivity"
3 parent="@android:style/Animation.Activity" >
4 <item name="android:activityOpenEnterAnimation">@anim/push_left_in</item>
5 <item name="android:activityOpenExitAnimation">@anim/push_left_out</item>
6 <item name="android:activityCloseEnterAnimation">@anim/push_right_in</item>
7 <item name="android:activityCloseExitAnimation">@anim/push_right_out</item>
8 </style>
9 2. 然后在themes.xml中
10 <style name="ThemeActivity">
11 <item name="android:windowAnimationStyle">@style/AnimationActivity</item>
12 <item name="android:windowNoTitle">true</item>
13 </style>
14 3. 在AndroidManifest.xml中为Activity指定theme.
使用代码设定:
通过调用 overridePendingTransition() 可以实时修改Activity的切换动画。
但需注意的是:该函数必须在调用startActivity()或finishe后立即调用,且只有效一次。
六、Drag
七、Sample:ViewFlipper实现最常见应用
1,定义四个动画 , fade_left_in fade_left_out fade_right_in fade_right_out
2,定义layout文件 。 <ViewAnimator> or <ViewFlipper>
3,写代码 , onCreate() 取得Flipper对象设置好属性 。
4,事件 , GestureDetector .
5, onFling() , 设置 viewFlipper设置动画以及调用下一个ViewGroup
八、案例(模仿Apple程序列表的抖动效果)
Steps:
1, 通过PackageManager 加载应用图标到GridView里
2,定义好item的shake动画 , longclick的时候 , 启动动画
3,随着鼠标的移动 , 判断进入到了哪个Dock (哪个单元格区域)PointToPosition,从区域转换为index , 然后交换单元格视图(Swap)(先交换adapter ,绑定视图,视图就交换了)
4,Drop的时候把原来的图标放到当前单元格
标签:android style blog http color io os 使用 java
原文地址:http://www.cnblogs.com/androidsj/p/3972552.html