12、高级商用界面开发

一、风格与主题

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的时候把原来的图标放到当前单元格

时间: 2024-09-27 07:23:57

12、高级商用界面开发的相关文章

界面开发的三层境界

关键词:GUI框架,UI编辑器,界面引擎,MVC 第一层境界:代码写死笔者大学时候开始学习的语言是C/C++,学习完基本的概念后,后面想开发有界面的应用程序接触的是win32,你会发现创建一个窗口或者一个button控件要写好多代码,例如配置标题,位置,大小,背景颜色,icon等等各种属性,api接口一大堆参数. win32创建窗口api HWND CreateWindow( LPCTSTR lpClassName, //窗口类型名称 LPCTSTR lpWindowName, //窗口名称 D

(转载)VS2010/MFC编程入门之五十二(Ribbon界面开发:创建Ribbon样式的应用程序框架)

上一节中鸡啄米讲了GDI对象之画刷CBrush,至此图形图像的入门知识就讲完了.从本节开始鸡啄米将为大家带来Ribbon界面开发的有关内容.本文先来说说如何创建Ribbon样式的应用程序框架. Ribbon界面就是微软从Office2007开始引入的一种为了使应用程序的功能更加易于发现和使用.减少了点击鼠标的次数的新型界面,从实际效果来看,不仅外观漂亮,而且功能直观,用户操作简洁方便. 鸡啄米将以图文结合的方式来说明利用MFC向导创建Ribbon样式的单文档应用程序框架的过程,其实Ribbon应

WIN32界面开发之三:DUI雏形开发(一)

http://blog.csdn.net/harvic880925/article/details/9491387 2013-07-26 09:26 3585人阅读 评论(12) 收藏 举报 目录(?)[+] 前言:这部分涉及工程比较大,所以我打算分开为两篇来写,第一篇完成基本框架的构建,第二篇添加上EVENT和NOTIFY机制. 完成目标:仿照DirectUI,完成一个基本雏形,开发一个布局控件(Dialog),和一个按钮控件(Button),通过XML来布局窗体,最后按钮响应点击.鼠标移动等

老男孩Python高级全栈开发工程师【真正的全套完整无加密】

课程大纲 老男孩python全栈,Python 全栈,Python教程,Django教程,Python爬虫, scrapy教程,python高级全栈开发工程师,本套教程,4部分完整无缺,课程完结,官方售价6800元. 课程全部都是不加密,全部都有声音-不是网上那种几块钱十几块钱那种加密没有声音或者课程不全,贪便宜花冤枉钱不说都会严重影响学习,耽误大量时间! 本套全栈课程,不说完全媲美线下教学,只要你肯坚持,不会比面授差太多-坚持学完找一份python开发类的工作完全没问题,另外对于学习方面的投资

JAVA 图形开发中组件对齐方法及界面开发

/*文章中用到的代码只是一部分,需要源码的可通过邮箱联系我 [email protected]*/ 在上篇博客中提到了JAVA图形界面开发时的两种布局,流式布局和边框布局. 在实际使用中可能会发现,往容器中添加组件往往并不能得到想要的结果.比如想上下对齐两个组件,而流式布局是从左到右的,此时就很难实现上下对齐,此篇文章将介绍两个方法. 1.直接使用坐标贴图 如下面这个计算器的制作 1 package Graphic; 2 3 import java.awt.BorderLayout; 4 imp

JAVA 图形界面开发基础详解

/*文章中用到的代码只是一部分,需要源码的可通过邮箱联系我 [email protected]*/ 与C的win32一样,JAVA也有自己的图形界面开发,将在此篇博客中对基础部分进行讲解. 1.Java提供的图形界面类有哪些? Java提供了两套图形界面 (1)AWT组建(基础) AWT组件是jdk1.0的时候推出的图形界面类,它是位于java.awt包下的类.   当时在开发AWT组件时,采用的语言是C和C++,并且还调用了操作系统底层的绘图函数来实现AWT组件(我们看到的图形界面实际上画出来

VS2010-MFC(Ribbon界面开发:创建Ribbon样式的应用程序框架)

转自:http://www.jizhuomi.com/software/251.html 上一节讲了GDI对象之画刷CBrush,至此图形图像的入门知识就讲完了.从本节开始将为大家带来Ribbon界面开发的有关内容.本文先来说说如何创建Ribbon样式的应用程序框架. Ribbon界面就是微软从Office2007开始引入的一种为了使应用程序的功能更加易于发现和使用.减少了点击鼠标的次数的新型界面,从实际效果来看,不仅外观漂亮,而且功能直观,用户操作简洁方便. 下面将以图文结合的方式来说明利用M

VS2010/MFC编程入门之五十二(Ribbon界面开发:创建Ribbon样式的应用程序框架)

上一节中鸡啄米讲了GDI对象之画刷CBrush,至此图形图像的入门知识就讲完了.从本节开始鸡啄米将为大家带来Ribbon界面开发的有关内容.本文先来说说如何创建Ribbon样式的应用程序框架. Ribbon界面就是微软从Office2007开始引入的一种为了使应用程序的功能更加易于发现和使用.减少了点击鼠标的次数的新型界面,从实际效果来看,不仅外观漂亮,而且功能直观,用户操作简洁方便. 鸡啄米将以图文结合的方式来说明利用MFC向导创建Ribbon样式的单文档应用程序框架的过程,其实Ribbon应

Vue+Node+MongoDB高级全栈开发

第1章 本地与服务器环境准备介绍微信公众号/小程序/域名/服务器的申请选购流程,在本地与线上服务器分别对项目的运行环境进行搭建部署,如 Node.js/Vue/Yarn/PM2/Nginx/MongoDB 等等,同时会来简单介绍下从本地通过 PM2 利用 Git 仓库直接往线上服务器部署以及 Nginx 端口映射解析特定域名的实现流程,最终准备好本地线上和外部业务环境为开发...1-1 导学1-2 课程简介1-3 申请认证公众服务号与小程序1-4 选购域名与备案解析域名1-5 选购配置服务器1-