使用HTML来生产Android界面

使用HTML来生产Android界面

(2013-03-11 17:50:39)

转载▼

  分类: Android

1. HTML 开发软件界面
   因为android软件开发分工目前还没有细化,程序员往往需要负责软件界面的开发,
   虽然软件的界面图片已经由美工设计好了,但如果使用layout技术把软件做成如图片所示的界面确实很困难,而且也比较耗时。
   Android通过WebView实现了JS代码与Java代码互相通信的功能,使的android软件的界面开发也可以采用HTML网页技术,
   这样,广大网页美工可以参与进android软件的界面开发工作,从而让程序员从中解脱出来。

2. WebView

WebView 控件可以显示一张网页。
   <WebView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:id="@+id/webView"

/>

首先要将一张由美工MM设计的精美的网页复制到项目中来,建议放在 assets 目录下,assets 目录下的资源将不会被添加到 R 文件中。
   然后在 Activity 里首先找到 WebView 控件,然后调用它的 loadUrl 方法,就可以载入一张网页,显示在界面上。
     WebView webView = (WebView) findViewById(R.id.webView);

webView.loadUrl("file:///android_asset/index.html");

注意这里用到的是文件访问协议:file:///,而我们项目中的 assets 文件夹部署到手机后,就变成了 android_asset。
        有两点注意:file:/// 是三个斜杠
                   是 asset 不是 assets

loadUrl 提供了一个很重要的重装后的方法,将在第4点说到。

3. 当然,这样一种机制太死板了,一个数据纯静态的网页,意义不大。
   Android 提供了一种与网页 JS 代码通信的机制。
   这种机制使 HTML 网页中,可以通过 JS 来访问 JAVA 对象的方法。
   这里又要用到 WebView 的另一个方法:addJavascriptInterface(Object obj, String interfaceName)

WebView 的作用就相当于 HTML 页面和 JAVA 对象的中间人,它们的所有活动都需要这个中间人来处理一下。
   例如,addJavascriptInterface 就可以将一个 JAVA 对象提供给 HTML 页面的 JS 代码来访问。
   仔细想一下,这技术也没什么稀奇的,无非就是反射的一种应用而已。被 WebView 来管理的 HTML 本身已不是传统意义的 HTML 静态网页了。
   因为,处理它的再也不是浏览器了,既然如此。HTML 的意义就仅剩下 ”一个普通文档“ 的意义了。既然如此,WebView 要怎么来解释这个文档,还不是它设计者一句话的事情。
   因此,其设计人员规定,当解释到类似 "contact.getContacts()" 的 JS 代码时,以 "contact" 作为键,找到它所对应的 JAVA 对象,再通过反射技术,调用这个对象的 getContacts() 方法。若方法有返回值,则将返回值返回到 JS 调用的地方。感觉过程甚至和 JSP 有点类似了。
   这是一种非常巧妙的思路。个人觉得,Android 可以照着这个思路,干得更彻底一点 —— 当然强烈鄙视最后变成了 "JSP"。
   contact.getContacts():中的 contact 最终之所以能作为键找到对应的 JAVA 对象,是因为在加载这张网页前。我们在程序中调用了 WebView 的 addJavascriptInterface 方法
   方法的第一个参数,就是要交给 WebView 这个中间人管理的POJO。第二个参数就是这个 JAVA 对象对外公开的名字,就是我上面说的 ”键“ 的概念。
   webView.addJavascriptInterface(new ContactsPlugin(), "contact");

于是,通过在 JS 里面使用 contact.getContacts() 就相当于执行了 : new ContactsPlugin().getContacts()

4. 在 JAVA 代码里访问 JS

方式是使用 WebView 的 loadUrl(),只不过这时候不再是 load 一张网页了,而是告诉 WebView,请帮我在你管辖下的 HTML 里找一段 JS 代码来执行。
   第一步:打开 webView 对 JavaScript 的支持(默认不支持):webView.getSettings().setJavaScriptEnabled(true);

第二步:让 webView 执行一段 JavaScript 代码 :webView.loadUrl("javascript:show(‘JAVA to JS‘)");

这句代码,将告诉 WebView,在它管辖下的 HTML 中执行这样一段 JS :show(‘JAVA to JS‘)

单把它看成一段 JS 代码,很明显,它是在调用一个方法。于是,这句代码的最终结果就是,HTML 中,我们定义的这样一个 JS 代码执行了:
     <script type="text/javascript">

function show(data) {

alert(data);

}

</script>

这个就更神奇了。
   但是只要我们转换一下思路,别把 HTML 当成以前传统的 HTML 、别把 JS 当成传统的 JS 就好。
   我个人觉得可以这样来理解,WebView 大概上讲有些类似于 WEB 服务器的概念了。只要我们将 JAVA 对象 和 所谓的HTML 交给了它管理,它会以特殊的方式来处理这两者被我们打上特殊标记的地方。最后拼凑出最终界面,显示给用户。

5. 例:
       ** 实现联系人列表显示。要求用户在启动程序之后,动态从数据库获取联系人信息,显示在界面上。
          点击联系人的电话号码,实现电话拨号。
          使用 HTML 语言来描述界面。
       ** 拷贝 index.html 到项目 assets 文件夹下
              * index.html

view plaincopy to clipboardprint?
01. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
02.                <html> 
03.                <head> 
04.                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
05.                <title>Insert title here</title> 
06.                <mce:script type="text/javascript"><!--  
07.                       
08.                     function show(jsondata){  
09.                                    
10.                             var jsonobjs = eval_r(jsondata);  
11.                             var table = document.getElementByIdx_xx_x("personTable");  
12.                             for(var y=0; y<jsonobjs.length; y++){  
13.                                    // 添加行  
14.                                    var tr = table.insertRow(table.rows.length);  
15.                                    // 编号列  
16.                                    var td1 = tr.insertCell(0);  
17.                                    td1.innerHTML = jsonobjs[y].id;  
18.                                          // 性名列  
19.                                    var td2 = tr.insertCell(1);  
20.                                    td2.align = "center";  
21.                                    td2.innerHTML = jsonobjs[y].name;  
22.                                          // 电话列,电话号码为超链接  
23.                                    var td3 = tr.insertCell(2);  
24.                                    td3.align = "center";  
25.                                    // <a href=‘javascript:contactsAction.call("139999999999")>139999999999</a> 
26.                                    td3.innerHTML = "<a href="javascript:contactsAction.call(\""+ jsonobjs[y].mobile+ "\")" mce_href="javascript:contactsAction.call(\""+ jsonobjs[y].mobile+ "\")">"+ jsonobjs[y].mobile+ "</a>";  
27.                                   }  
28.                     }  
29.                  
30.// --></mce:script> 
31.               
32.                </head> 
33.                <!-- 页面加载的时候将执行下面的 JS 代码,将调用 ContactsPlugin 的 getContacts() 方法--> 
34.                <body > 
35.                   <table border="0" width="100%" id="personTable" cellspacing="0"> 
36.                            <tr> 
37.                                   <td width="20%">编号</td><td width="40%" align="center">姓名</td><td align="center">电话</td> 
38.                            </tr> 
39.                   </table> 
40.                   <a href="javascript:window.location.reload()" mce_href="javascript:window.location.reload()">刷新</a> 
41.                </body> 
42.</html>

** Activity 里初始化联系人数据,并调用 HTML 中的 show 方法想表格增加行,添加联系人数据到表格显示
              * MainActivity

view plaincopy to clipboardprint?
01.public class MainActivity extends Activity {  
02.                    private final static String TAG = "HtmlUIMainActivity";  
03.                    private WebView webView;  
04.                    private ContactService contactService;  
05.                     
06.                     @Override 
07.                     public void onCreate(Bundle savedInstanceState) {  
08.                          super.onCreate(savedInstanceState);  
09.                          setContentView(R.layout.main);  
10.                          contactService = new ContactService();  
11.                          webView = (WebView) findViewById(R.id.webView);  
12.                          webView.getSettings().setJavaScriptEnabled(true);  
13.                          webView.addJavascriptInterface(new ContactsPlugin(), "contactsAction");  
14.                          webView.loadUrl("file:///android_asset/index.html");  
15.                      }  
16.                  
17.                       
24.                      private class ContactsPlugin {  
25.                              
29.                             @SuppressWarnings("unused")  
30.                         public void getContacts() {  
31.                                    List<Contact> contacts =contactService.getContacts();  
32.                                    try {  
33.                                       JSONArray array  = new JSONArray();  
34.                                       for(Contact contact : contacts) {  
35.                                              JSONObject jsonObject = new JSONObject();  
36.                                              jsonObject.put("id", contact.getId());  
37.                                              jsonObject.put("mobile", contact.getMobile());  
38.                                              jsonObject.put("name", contact.getName());  
39.                                              array.put(jsonObject);  
40.                                       }  
41.                                       String json = array.toString();  
42.                                       webView.loadUrl("javascript:show(‘"+ json +"‘)");  
43.                                 } catch (JSONException e) {  
44.                                       Log.i(TAG, e.toString());  
45.                                 }  
46.                              }  
47.                               
50.                              @SuppressWarnings("unused")  
51.                          public void call(String phoneCode) {  
52.                                    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phoneCode));  
53.                                    startActivity(intent);  
54.                              }  
55.                      }  
       ** 布局文件,只需要定义一个 WebView 就可以了
              * main.xml

view plaincopy to clipboardprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
03.       android:orientation="vertical" 
04.       android:layout_width="fill_parent" 
05.       android:layout_height="fill_parent" 
06.       > 
07.       <WebView   
08.         android:layout_width="fill_parent" 
09.         android:layout_height="fill_parent" 
10.         android:id="@+id/webView" 
11.        /> 
12.</LinearLayout> 
       ** 功能清单,需要声明拨号权限
              * AndroidManifest.xml

view plaincopy to clipboardprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<manifest xmlns:android="http://schemas.android.com/apk/res/android
03.        package="wjh.android.htmlui" 
04.        android:versionCode="1" 
05.        android:versionName="1.0"> 
06.<application android:icon="@drawable/icon" android:label="@string/app_name"> 
07.            <activity android:name=".MainActivity" 
08.                 android:label="@string/app_name"> 
09.            <intent-filter> 
10.                <action android:name="android.intent.action.MAIN" /> 
11.                <category android:name="android.intent.category.LAUNCHER" /> 
12.            </intent-filter> 
13.            </activity> 
14.               
15.</application> 
16.<uses-sdk android:minSdkVersion="8" /> 
17.<uses-permission android:name="android.permission.CALL_PHONE"/> 
18.</manifest>

6. 流程
   1. 使用 HTML 来描述软件界面。

2. 当用户在界面中触发一个业务感兴趣的事件的时候,触发并执行一段特殊的 JS 代码。
   3. 这段特殊的 JS 代码可以被 WebView 解析,并最终调用 JAVA Bean 的某个方法,完成业务操作。
   4. 在 JAVA 代码中,通过 WebView 在页面执行一段 JS 代码,实现对用户操作的响应或对页面展示的数据做动态改变。

写着写着,才发现,成 AJAX 了。不禁有点兴奋。这至少比我们自己写 XML 半标记、半代码的来实现界面要好多了。无论从软件开发分工、各层之间的解耦、以及程序员的舒适度来看。

7. 缺点,界面效果貌似不如用 layout 界面 XML 文件开发的软件界面华丽。
   就目前来说,对 HTML、JS、CSS 等 web 技术支持到何种程度,还有待进一步发现和总结。
   但是我目前做的测试表明,基本上一些 W3C 标准,和一些公认的规范,WebView 都是支持的。
   至于到底两种方式谁好。一方面来说,似乎就成了桌面应用和WEB应用的争执范畴了。

时间: 2024-08-25 00:06:10

使用HTML来生产Android界面的相关文章

[转]使用HTML来生产Android界面

1. HTML 开发软件界面   因为android软件开发分工目前还没有细化,程序员往往需要负责软件界面的开发,   虽然软件的界面图片已经由美工设计好了,但如果使用layout技术把软件做成如图片所示的界面确实很困难,而且也比较耗时.   Android通过WebView实现了JS代码与Java代码互相通信的功能,使的android软件的界面开发也可以采用HTML网页技术,   这样,广大网页美工可以参与进android软件的界面开发工作,从而让程序员从中解脱出来. 2. WebView W

android界面设计之布局管理

谈到android界面设计,各种布局样式不得不提!传统的布局方式有6种,我们会一一介绍. 在android studio2.2版本之后出现了一款超棒的布局方式,真正意义上的所见即所得,后面我们也会讲到! 1.LinearLayout:线性布局:线性布局又有两种,"垂直布局"和"水平布局". 垂直布局每一行只能有一个控件(自己嵌套的不算): 水平布局只有一行,所有的控件依次从左向右排列: linearLayout中有一个重要的属性 android:layout_wei

Android界面编程——导航栏及菜单(六)

Android界面编程--导航栏及菜单 2.7导航栏及菜单 2.7.1  ActionBar ActionBar是Android3.0(API 11)开始增加的新特性,ActionBar出现在活动窗口的顶部,可以显示标题.icon.Actions按钮.可交互View,可实现应用程序级的导航,如图2.7-1所示 图2.7-1 其中 1. App icon: 主要用于展示App的Logo,如果当前界面不是一级界面,还可以展示返回航. 2.View Control: 用于切换不同的视图或者展示非交互信

android界面设计之布局

一.线性布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orie

iOS中xib与storyboard原理,与Android界面布局的异同

用文本标记语言来进行布局,用的最多的应该是HTML语言.HTML可以理解为有一组特殊标记的XML语言. 一.iOS中xib与storyboard显示原理 在iOS中主要的布置界面的方式有3种:代码,xib,storyboard. 1. 代码 代码布置界面是万能的,但通常很复杂.布置一个简单的界面可能需要很多行代码,因此十分繁琐. 下面为创建一个按钮的代码,最少也要3行: UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd

Android界面性能调优手册

转载:https://androidtest.org/android-graphics-performance-pattens/#11 界面是 Android 应用中直接影响用户体验最关键的部分.如果代码实现得不好,界面容易发生卡顿且导致应用占用大量内存. 我司这类做 ROM 的公司更不一样,预装的应用一定要非常流畅,这样给客户或用户的第一感觉就是快.又卡又慢的应用体验,会影响客户或用户对产品的信心和评价,所以不可忽视. 目录 一. Android渲染知识 1.1 绘制原理 1.2 掉帧 1.3

看大家android界面设计是拿Android Design UI Kit设计的,不直接在eclipse里设计,但是UI KIT怎么用呢

============问题描述============ Android 4.4 Design UI Kit (Nexus 4 version)打开十psd格式的,看网上说吧psd里面自己需要用到的东西保存为png格式,然后是要把png格式的图片当做android控件的背景使用? 其他类似的工具呢? ============解决方案1============ 一切不问是不是就问为什么的都是耍流氓,不知道你是怎么得出"android界面设计是拿Android Design UI Kit设计的,不直

关于Android界面编程与视图(View)组件

UI组件--------------->android.widget.* View组件------------->android.view.* 视图(View)组件 所有UI组件都是建立在视图(View)组件.容器(ViewGroup)组件基础之上的. UI组件继承之View组件 ViewGroup----------->作为其他组件的容器使用. ViewGroup包含View组件即 (UI组件---->继承自View组件. ViewGroup组件---->继承自View组件

[Android]界面控件

1. 引用系统自带样式 字体大小 对于能够显示文字的控件(如TextView EditText RadioButton Button CheckBox Chronometer等等),你有时需要控制字体的大小.Android平台定义了三种字体大小. "?android:attr/textAppearanceLarge" "?android:attr/textAppearanceMedium" "?android:attr/textAppearanceSmal