整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

第3讲 小程序框架

遇见周大侠(网名:程序猿),长沙奥科领航信息技术公司的资深软件开发工程师。他的软件开发系列课件和项目,凝聚了多年的专业积累与热情。每套课件都包含丰富的案例和深入的知识点解析,每一讲都配备了精心设计的课后作业,旨在为热爱编程的你提供最佳编程实践。是教师备课的得力助手,是学生学习的贴心伴侣,亦是毕业设计的灵感源泉。现在,请搜索微信小程序「奥科领航信息技术 」,让我们一起深入代码的世界,探索无限可能!」


目录:

  • 小程序框架
  • 逻辑层
  • 视图层

一、小程序框架

1.1 框架概述

小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。

整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。

1.2 数组绑定

同学们,还记得Vue(实现了MVVM设计模式)中的数据绑定吗?在Vue中,表单元素和模型实现了双向的数据绑定,当一端发生改变,另一端会同步改变。微信小程序也实现了类似的功能!

微信小程序框架的核心是一个响应式的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。

示例1:在index页面的一个view标签中显示一个默认的字符串“我爱你”,点击[确定]按钮,view标签显示为“我恨你”。


<!-- index.wxml -->
<!-- 以文本插值{{}}的方式显示数据 -->
<!-- view标签相当于HTML中的div -->
<view>{{message}}</view>
<!-- 定义一个按钮 -->
<!-- bind:tap事件相当于HTML中的click。changeValue是一个自定义的事件处理函数名称 -->
<!-- bind:tap可以写成bindtap -->
<button type="primary" bind:tap="changeValue">修改值</button>

// index.js
// Page是页面的入口函数
Page({
// 在data选项中定义数据
data: {
message: "我爱你"
},
// 定义函数
changeValue: function () {
// setData()函数的作用:修改data选项中所定义的数据
// 要修改data选项中所定义的数据,只能通过调用setData()函数来实现!
this.setData({
message: "我恨你"
})
}
})

代码说明:

  • 我们通过框架将逻辑层数据中的 message与视图层的 message进行了绑定,所以在页面一打开的时候会显示“我爱你”;
  • 当点击按钮的时候,触发bindtap事件,视图层会发送 changeValue 给逻辑层,逻辑层找到并执行对应的事件处理函数;
  • 回调函数触发后,逻辑层执行 setData 的操作,将 data 中的 message从“我爱你” 变为“我恨你”,因为该数据和视图层已经绑定了,从而视图层会自动改变为“我恨你”!

小结:

  1. 点击命令按钮,会触发bindtap事件。bindtap事件相当于HTML标签的onclick事件。bindtap可以写成bind:tap
  2. 要修改data中的属性值,必须通过调用setData()函数来修改。

示例2:在文本框中输入值,在view中同步显示。


<!-- index.wxml -->
<!-- 定义一个文本框 -->
<!-- 在文本框中每输入一个字符,都会触一次bindinput事件 -->
<input type="text" bindinput="changeValue" placeholder="请输入值"/>
<view>{{message}}</view>

// index.js
Page({
data: {
message: ""
},
// 定义函数
// 参数e代表一个事件对象,里面封装了本次事件触发之后所产生的一些数据
changeValue: function(e){
// e.detail.value:获取文本框中的值
// detail:详细;value:值
console.log(e);
console.log(e.detail.value);
this.setData({
message: e.detail.value
})
}
})

小结:在文本框中输入文字,会触发bindinput事件。bindinput事件相当于HTML中的oninput事件。

1.3 页面管理

框架管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到框架中,其他的一切复杂的操作都交由框架处理。

1.4 基础组件

框架提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序。

见官网:

https://developers.weixin.qq.com/miniprogram/dev/component/

1.5 丰富的API

框架提供丰富的微信原生API,可以方便的调起微信提供的能力,如获取用户信息、本地存储、支付功能等。

见官网:

https://developers.weixin.qq.com/miniprogram/dev/api/

二、逻辑层

2.1 注册小程序

每个小程序都需要在 app.js 中调用 App() 方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等。

App() 必须在 app.js 中调用,必须调用且只能调用一次,不然会出现无法预期的后果。

App({
...
});

各个回调函数及其说明请见官方文档:

https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html

2.2 注册页面

对于小程序中的每个页面,都需要在页面对应的 js 文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。

Page({
...
});

请见官方文档:

https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page.html

2.3 页面生命周期

onLoad->onShow->onReady->onHide->onUnload

2.4 页面路由

从一个页面跳转到另一个页面,叫做页面路由。

页面路由有四个API:

  • navigateTo:导航
  • redirectTo:重定向
  • switchTab:切换Tab页面
  • reLauhc:重启

见官方文档:

https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/route.html

2.4.1 示例1

默认显示首页(index),然后点击底部导航的日志(log),观察各个生命周期函数的输出信息。

2.4.1.1 准备工作

(1)app.json

{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/orders/orders",
"pages/cart/cart",
"pages/home/home",
"pages/a/a"
],
"window": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "中华人民共和国",
"navigationBarBackgroundColor": "#0000ff"
},
"style": "v2",
"componentFramework": "glass-easel",
"sitemapLocation": "sitemap.json",
"lazyCodeLoading": "requiredComponents",
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "./images/1.png",
"selectedIconPath": "./images/1_1.png"
},{
"pagePath": "pages/logs/logs",
"text": "日志",
"iconPath": "./images/2.png",
"selectedIconPath": "./images/2_2.png"
},{
"pagePath": "pages/orders/orders",
"text": "我的订单",
"iconPath": "./images/3.png",
"selectedIconPath": "./images/3_3.png"
},{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "./images/4.png",
"selectedIconPath": "./images/4_4.png"
}]
}
}

(2)index.js

Page({
onReady: function(){
console.log("index:ready函数执行了");
},
onUnload: function(){
console.log("index:unload函数执行了");
},
onLoad: function(){
console.log("index:load函数执行了");
},
onShow: function(){
console.log("index:show函数执行了");
},
onHide: function(){
console.log("index:hide函数执行了");
}
})

(3)logs.js

Page({
onReady: function(){
console.log("logs:ready函数执行了");
},
onUnload: function(){
console.log("logs:unload函数执行了");
},
onLoad: function(){
console.log("logs:load函数执行了");
},
onShow: function(){
console.log("logs:show函数执行了");
},
onHide: function(){
console.log("logs:hide函数执行了");
}
})

(4)a.js

Page({
onReady: function(){
console.log("a:ready函数执行了");
},
onUnload: function(){
console.log("a:unload函数执行了");
},
onLoad: function(){
console.log("a:load函数执行了");
},
onShow: function(){
console.log("a:show函数执行了");
},
onHide: function(){
console.log("a:hide函数执行了");
}
})

2.4.1.1 控制台输出

(1)初始显示首页的输出

(2)切换到底部tab栏的日志的输出

从输出结果可知,原来的首页只是被隐藏了,并没有被卸载。

(3)再切换到首页

2.4.2 示例2

从首页导航到A页面。

// index.js
Page({
...
navigateToA: function(){
// 通过导航的方式进行页面路由
wx.navigateTo({
url: '../a/a',
})
},
})

<!-- index.wxml -->
<button type="primary" bind:tap="navigateToA">导航到A页面</button>

2.4.2 示例3

从首页重定向到A页面。

// index.js
Page({
...
redirectToA: function(){
// 通过导航的方式进行页面路由
wx.redirectTo({
url: '../a/a',
})
},
})

<!-- index.wxml -->
...
<button type="primary" bind:tap="redirectToA">重定向到A页面</button>

更加详细的路由资料见"小程序路由小结.md"文档。

2.5 API

见官方文档:

https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/api.html#API

前面我们已经用到了wx.navigateTo()、wx.redirectTo()、wx.navigateBack()、wx.switchTab()等API。现在我再举一个获取用户信息API。先看效果:


<!-- index.wxml -->
<view class="tip">首页</view>
<button type="primary" bindtap="getUserInfo">获取用户信息</button>
<view>{{userInfo.nickName}}</view>
<view wx:if="{{userInfo.gender}}">{{userInfo.gender == 1? "男" : "女"}}</view>
<image src="{{userInfo.avatarUrl}}"></image>

// index.js
Page({
data: {
userInfo: {}
},
getUserInfo: function(e){
wx.getUserProfile({
desc: "用于完善用户资料",
success: (res) => {
console.log(res.userInfo);
this.setData({
userInfo: res.userInfo
});
}
})
}
})

点击模拟器中的【获取用户信息】按钮,没有显示像上图中那样的底部弹框,在控制台输出的用户信息如下:

这是因为从2022年10月26日开始,wx.getUserProfile接口被收回了:

如果将基础库版本调整为2.21.2或者以下,则可以。

三、视图层

框架的视图层由 WXML 与 WXSS 编写。

将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。

  • WXML(WeiXin Markup language) 用于描述页面的结构。
  • WXSS(WeiXin Style Sheet) 用于描述页面的样式。

3.1 wxml

WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。

3.1.1 数组绑定

语法:{{}}

// index.js
Page({
data: {
message: "初始值"
}
})

<!-- index.wxml -->
<view>{{message}}</view>

3.1.2 条件渲染

语法:wx:if、wx:elif、wx:else

// index.js
Page({
data: {
week: (new Date()).getDay()
}
})

<!-- index.wxml -->
<view wx:if="{{week >= 1 && week <= 5}}">
星期一到星期五,学习时间
</view>
<view wx:elif="{{week == 6}}">
星期六,购物时间
</view>
<view wx:else>
星期天,休息时间
</view>

3.1.3 列表渲染

语法:wx:for

// index.js
Page({
data: {
students: [{id: 10001, name: "张三"}, {id: 10002, name: "李四"}]
}
})

<!-- index.wxml -->
<block wx:for="{{students}}">
<view style="border-bottom: 1px solid #000000">
<view>序号:{{index}}</view>
<view>编号:{{item.id}}</view>
<view>姓名:{{item.name}}</view>
</view>
</block>

代码说明:

  • <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。在上面的例子中,也可以直接将wx:for写在应用了样式的那个view上;
  • 默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为item;
  • 使用 wx:for-item 可以指定数组当前元素的变量名;
  • 使用 wx:for-index 可以指定数组当前下标的变量名;

课堂练习:渲染出一个九九乘法口诀表。

<block wx:for="{{[1,2,3,4,5,6,7,8,9]}}" wx:for-item="i">
<view>
<block wx:for="{{[1,2,3,4,5,6,7,8,9]}}" wx:for-item="j">
<text>{{i}} * {{j}} = {{i * j}}</text>
</block>
</view>
</block>

关于wxk:key的说明。官方解释:当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。通俗的理解:在不使用 wx:key的情况下, 如果 array 内的数据发生改变,则会重新创建每个Item对象然后渲染列表,费时费力。而在使用 wx:key的情况下,如果array中的数据发生改变,只是将对应的对象重新排序。未发生变化的对象,不会重新创建。有两种使用方法:

  • 第一种:wx:key = “字符串或数字”,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
  • 第二种:保留关键字 *this,代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。

3.2 wxss

WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。

WXSS 用来决定 WXML 的组件应该怎么显示。

为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。

与 CSS 相比,WXSS 扩展的特性有:

  • 尺寸单位尽量用rpx:responsive pixel,可以根据屏幕宽度进行自适应
  • 样式导入使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用“;”表示语句结束。

3.3 数据绑定

在 WXML 中,普通的属性的绑定是单向的。

<input type = "text" value="{{value}}" />

Page({
data: {
value: ""
}
})

如果使用 this.setData({ value: 'leaf' }) 来更新 value ,this.data.value 和输入框的中显示的值都会被更新为 leaf ;但如果用户修改了输入框里的值,却不会同时改变 this.data.value 。

如果需要在用户输入的同时改变 this.data.value ,需要借助简易双向绑定机制。此时,可以在对应项目之前加入 model: 前缀:

<input model:value="{{value}}" />

这样,如果输入框的值被改变了, this.data.value 也会同时改变。同时, WXML 中所有绑定了 value 的位置也会被一同更新。

示例:在文本框中输入值,在view中同步显示。

// index.js
Page({
data: {
value: ""
}
})

<!-- index.wxml -->
<input type = "text" placeholder = "请输入文字" model:value="{{message}}"/>
<view>{{message}}</view>

上面的双向绑定,只能实现简单数据类型(比如字符串、数字)的双向绑定。复杂数据(比如对象、数组)等无法实现双向绑定,比如:

// index.js
Page({
data: {
student: {
id: 1,
name: "张三"
}
}
})

<!-- index.wxml -->
<input type = "text" modal:value = "{{student.name}}">
<view>{{student.name}}</view>

一篇文章讲解“模型-模板布局之全局配置方式”,本篇文章讲解“模板-模板布局之模板标签方式”。


模板标签方式

这种布局模板不需要在配置文件中设置任何参数,也不需要开启layout_on,直接在模板文件中指定布局模板即可,相关的布局模板调整也在模板中进行。

以前面的输出模板为例,这种方式的入口还是在index/index.html模板,但是我们可以修改下index模板文件的内容,在头部增加下面的布局标签(记得首先关闭前面的layout_on设置,否则可能出现布局循环):

1)基本使用

①在index.html模板头部增加布局标签

②在布局模板view/layout.html中添加布局模板的{__CONTENT__}特定字符串

预览:

{layout name="layout" /}表示当前模板文件需要使用layout.html布局模板文件,而布局模板文件的写法和上面第一种方式(全局布局方式)是一样的。当渲染index/index.html模板文件的时候,如果读取到layout标签,则会把当前模板的解析内容替换到layout布局模板的{__CONTENT__}特定字符串。

注意:

1. 一个模板文件中只能使用一个布局模板,如果模板文件中没有使用任何layout标签则表示当前模板不使用任何布局。

2)使用其他的布局模板

如果需要使用其他的布局模板,可以改变layout的name属性,例如:

①在index.html模板中设置使用其他布局模板

②在view/public/下新建lay.html布局模板

预览:

3)指定要替换的特定字符串

还可以在layout标签里面指定要替换的特定字符串:

①在index.html模板中指定要替换的特定字符串:

②修改public/lay.html布局模板中的特定字符串

预览:

注意:

1. 布局模板的默认替换的特定字符串为{__CONTENT__}。

2. 以上设置的特定字符串为[__REPLACE__],那在布局模板中就要使用[__REPLACE__],替换字符串的定界符可以自定义,一般为花括号“{__REPLACE__}”

​ThinkPHP5连载为卓象程序员原创,转载请联系卓象程序员

关注卓象程序员,定期发布技术文章

下一篇讲解“模板-模板布局之动态方法布局”

先使用jQuery选择器获取到想要绑定click事件的img元素,然后可以直接绑定click方法,也可以通过bind方法绑定。这里详细介绍一下bind方法。jQuery 事件 - bind() 方法 —— 定义和用法

html中如何给图片添加点击事件的详解


bind() 方法为被选元素添加一个或多个事件处理程序,并规定事件发生时运行的函数。

jQuery 事件 - bind() 方法 ——将事件和函数绑定到元素

规定向被选元素添加的一个或多个事件处理程序,以及当事件发生时运行的函数。

jQuery 事件 - bind() 方法——语法

1 $(selector).bind(event,data,function)

jQuery 事件 - bind() 方法——参数描述

event 必需。规定添加到元素的一个或多个事件。由空格分隔多个事件。必须是有效的事件。

data 可选。规定传递到函数的额外数据。

function 必需。规定当事件发生时运行的函数。

实例:


1 //直接给所有img标签绑定click事件

2 $("img").click(function(){

3 alert('你点击了图片');

4 })

5

6 //使用bind方法绑定click事件

7 $("img").bind("click",function(){

8 alert('你点击了图片');

9 })


Html 的img标签添加点击事件


1 package com.topnews;

2

3 import java.util.ArrayList;

4

5 import android.annotation.SuppressLint;

6 import android.app.Activity;

7 import android.app.Fragment;

8 import android.content.Context;

9 import android.content.Intent;

10 import android.graphics.Bitmap;

11 import android.os.AsyncTask;

12 import android.os.Bundle;

13 import android.text.TextUtils;

14 import android.util.Log;

15 import android.view.View;

16 import android.view.ViewGroup.LayoutParams;

17 import android.webkit.WebChromeClient;

18 import android.webkit.WebSettings;

19 import android.webkit.WebView;

20 import android.webkit.WebViewClient;

21 import android.webkit.WebSettings.LayoutAlgorithm;

22 import android.widget.Button;

23 import android.widget.FrameLayout;

24 import android.widget.ProgressBar;

25 import android.widget.TextView;

26

27 import com.topnews.base.BaseActivity;

28 import com.topnews.bean.NewsEntity;

29 import com.topnews.service.NewsDetailsService;

30 import com.topnews.tool.BaseTools;

31 import com.topnews.tool.DataTools;

32 import com.topnews.tool.DateTools;

33

34 @SuppressLint("JavascriptInterface")

35 public class DetailsActivity extends BaseActivity {

36 private TextView title;

37 private ProgressBar progressBar;

38 private FrameLayout customview_layout;

39 private String news_url;

40 private String news_title;

41 private String news_source;

42 private String news_date;

43 private NewsEntity news;

44 private TextView action_comment_count;

45 WebView webView;

46

47 @Override

48 protected void onCreate(Bundle savedInstanceState) {

49 // TODO Auto-generated method stub

50 super.onCreate(savedInstanceState);

51 setContentView(R.layout.details);

52 setNeedBackGesture(true);// 设置需要手势监听

53 getData();

54 initView();

55 initWebView();

56 }

57

58 /* 获取传递过来的数据 */

59 private void getData() {

60 news = (NewsEntity) getIntent().getSerializableExtra("news");

61 news_url = news.getSource_url();

62 news_title = news.getTitle();

63 news_source = news.getSource();

64 news_date = 65DateTools.getNewsDetailsDate(String.valueOf(news.getPublishTime()));

66 }

67

68 private void initWebView() {

69 webView = (WebView) findViewById(R.id.wb_details);

70 LayoutParams params = new 71LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

72 if (!TextUtils.isEmpty(news_url)) {

73 WebSettings settings = webView.getSettings();

74 settings.setJavaScriptEnabled(true);// 设置可以运行JS脚本

75 // settings.setTextZoom(120);//Sets the text zoom of the page in

76 // percent. The default is 100.

77 settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

78 // settings.setUseWideViewPort(true); //打开页面时, 自适应屏幕

79 // settings.setLoadWithOverviewMode(true);//打开页面时, 自适应屏幕

80 settings.setSupportZoom(false);// 用于设置webview放大

81 settings.setBuiltInZoomControls(false);

82 webView.setBackgroundResource(R.color.transparent);

83 // 添加js交互接口类,并起别名 imagelistner

84 webView.addJavascriptInterface(new 85JavascriptInterface(getApplicationContext()), "imagelistner");

86 webView.setWebChromeClient(new MyWebChromeClient());

87 webView.setWebViewClient(new MyWebViewClient());

88 Log.i("info", "news_url:" + news_url);

89 Log.i("info", "news_title:" + news_title);

90 Log.i("info", "news_source:" + news_source);

91 Log.i("info", "news_date:" + news_date);

92 new MyAsnycTask().execute(news_url, news_title, news_source + " " + 93news_date);

94 }

95 }

96

97 private void initView() {

98 title = (TextView) findViewById(R.id.title);

99 progressBar = (ProgressBar) findViewById(R.id.ss_htmlprogessbar);

100 customview_layout = (FrameLayout) 101findViewById(R.id.customview_layout);

102 // 底部栏目

103 action_comment_count = (TextView) 104findViewById(R.id.action_comment_count);

105

106 progressBar.setVisibility(View.VISIBLE);

107 title.setTextSize(13);

108 title.setVisibility(View.VISIBLE);

109 title.setText(news_url);

110 action_comment_count.setText(String.valueOf(news.getCommentNum()));

111 }

112

113 @Override

114 public void onBackPressed() {

115 super.onBackPressed();

116 overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);

117 }

118

119 private class MyAsnycTask extends AsyncTask<string, string,="" string=""> {

120

121 @Override

122 protected String doInBackground(String... urls) {

123 String data = NewsDetailsService.getNewsDetails(urls[0], urls[1], urls[2]);

124 Log.i("info", "MyAsnycTask.data:" + data);

125 return data;

126 }

127

128 @Override

129 protected void onPostExecute(String data) {

130 webView.loadDataWithBaseURL(null, data, "text/html", "utf-8", null);

131 }

132 }

133

134 // 注入js函数监听

135 private void addImageClickListner() {

136 // 这段js函数的功能就是,遍历所有的img几点,并添加onclick函数,在还是执137 行的时候调用本地接口传递url过去

138 webView.loadUrl("javascript:(function(){" + "var objs = 139document.getElementsByTagName(\"img\");" + "var imgurl=''; "

140 + "for(var i=0;i<objs.length;i++) "="" +="" "{"="" 141"imgurl+="objs[i].src+',';"" objs[i].onclick="function()" {="" 142window.imagelistner.openimage(imgurl);="" }="" "}"="" "})()");="" js通信接口="" 143public="" class="" javascriptinterface="" private="" context="" context;="" 144javascriptinterface(context="" context)="" this.context="context;" void="" 145openimage(string="" img)="" string[]="" imgs="img.split(",");" 146arraylist<string=""> imgsUrl = new ArrayList<string>();

147 for (String s : imgs) {

148 imgsUrl.add(s);

149 Log.i("图片的URL>>>>>>>>>>>>>>>>>>>>>>>", s);

150 }

151 Intent intent = new Intent();

152 intent.putStringArrayListExtra("infos", imgsUrl);

153 intent.setClass(context, ImageShowActivity.class);

154 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

155 context.startActivity(intent);

156 }

157 }

158

159 // 监听

160 private class MyWebViewClient extends WebViewClient {

161 @Override

162 public boolean shouldOverrideUrlLoading(WebView view, String url) {

163 return super.shouldOverrideUrlLoading(view, url);

164 }

165

166 @Override

167 public void onPageFinished(WebView view, String url) {

168 view.getSettings().setJavaScriptEnabled(true);

169 super.onPageFinished(view, url);

170 // html加载完成之后,添加监听图片的点击js函数

171 addImageClickListner();

172 progressBar.setVisibility(View.GONE);

173 webView.setVisibility(View.VISIBLE);

174 }

175

176 @Override

177 public void onPageStarted(WebView view, String url, Bitmap favicon) {

178 view.getSettings().setJavaScriptEnabled(true);

179 super.onPageStarted(view, url, favicon);

180 }

181

182 @Override

183 public void onReceivedError(WebView view, int errorCode, String description, 184String failingUrl)

185 {

progressBar.setVisibility(View.GONE);

super.onReceivedError(view, errorCode, description, failingUrl);

}

}

private class MyWebChromeClient extends WebChromeClient {

@Override

public void onProgressChanged(WebView view, int newProgress) {

// TODO Auto-generated method stub

if (newProgress != 100) {

progressBar.setProgress(newProgress);

}

super.onProgressChanged(view, newProgress);

}

}

}</string></objs.length;i++)></string,>


// NewsDetailsService.java


1 package com.topnews.service;

2

3 import java.io.IOException;

4 import org.jsoup.Jsoup;

5 import org.jsoup.nodes.Document;

6 import org.jsoup.nodes.Element;

7

8 import android.text.TextUtils;

9

10 public class NewsDetailsService {

11 public static String getNewsDetails(String url, String news_title,

12 String news_date) {

13 Document document = null;

14 String data = "" +

15 "<center><h2 style="'font-size:16px;'">" + news_title + "</h2></center>";

16 data = data + "<p align="'left'" style="'margin-left:10px'">"

17 + "<span style="'font-size:10px;'">"

18 + news_date

19 + "</span>"

20 + "</p>";

21 data = data + "<hr size="'1'">";

22 try {

23 document = Jsoup.connect(url).timeout(9000).get();

24 Element element = null;

25 if (TextUtils.isEmpty(url)) {

26 data = "";

27 element = document.getElementById("memberArea");

28 } else {

29 element = document.getElementById("artibody");

30 }

31 if (element != null) {

32 data = data + element.toString();

33 }

34 data = data + "";

35 } catch (IOException e) {

36 e.printStackTrace();

37 }

38 return data;

39 }

40 }

以上就是html中如何给图片添加点击事件的详解的详细内容,