
如何用PHP读取Excel文件数据及内容信息
在文章开始介绍前,大家需要了解一下PHPExcel是什么?PHPExcel 就是一个用来操作Office Excel 文档的PHP类库。接下来讲解如何利用PHPExcel类库将Excel表格内的信息内容读取出来,完整代码如下:
<?php
$fileName = "1.xls";
if (!file_exists($fileName)) {
return "文件不存在!";
}
// 引入PHPExcel
require_once "./PHPExcel/IOFactory.php";
// 载入当前文件
$phpExcel = PHPExcel_IOFactory::load($fileName);
// 设置为默认表
$phpExcel->setActiveSheetIndex(0);
// 获取表格数量
$sheetCount = $phpExcel->getSheetCount();
// 获取行数
$row = $phpExcel->getActiveSheet()->getHighestRow();
// 获取列数
$column = $phpExcel->getActiveSheet()->getHighestColumn();
echo "表格数目为:$sheetCount" . "表格的行数:$row" . "列数:$column";
$data = [];
// 行数循环
for ($i = 1; $i <= $row; $i++) {
// 列数循环
for ($c = 'A'; $c <= $column; $c++) {
$data[] = $phpExcel->getActiveSheet()->getCell($c . $i)->getValue();
}
echo "
";
print_r($data);
}
在上述代码中,先if判断Excel表格是否存在,再用require_once引入PHPExcel类库中IOFactory.php这个类,然后使用PHPExcel类库的一个方法载入Excel文件,这里将载入的Excel文件赋值于$phpExcel变量。
然后再将$phpExcel变量通过分别指定相应的方法来获取Excel表格的数目、行数、列数以及通过setActiveSheetIndex(0)方法设置这个表格为默认(0表示默认)。
此时输出表格的数目、行数、列数的结果,通过浏览器访问的结果就出来了。然后我们用for循环遍历出表格的所有内容,再定义一个数组$data来接收这些内容。以上就是为大家分享的内容了,如果大家还是存在不了解的地方,可以留言咨询我们。
本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。
在文章开始介绍前,大家需要了解一下PHPExcel是什么?PHPExcel 就是一个用来操作Office Excel 文档的PHP类库。接下来讲解如何利用PHPExcel类库将Excel表格内的信息内容读取出来,完整代码如下:
<?php
$fileName = "1.xls";
if (!file_exists($fileName)) {
return "文件不存在!";
}
// 引入PHPExcel
require_once "./PHPExcel/IOFactory.php";
// 载入当前文件
$phpExcel = PHPExcel_IOFactory::load($fileName);
// 设置为默认表
$phpExcel->setActiveSheetIndex(0);
// 获取表格数量
$sheetCount = $phpExcel->getSheetCount();
// 获取行数
$row = $phpExcel->getActiveSheet()->getHighestRow();
// 获取列数
$column = $phpExcel->getActiveSheet()->getHighestColumn();
echo "表格数目为:$sheetCount" . "表格的行数:$row" . "列数:$column";
$data = [];
// 行数循环
for ($i = 1; $i <= $row; $i++) {
// 列数循环
for ($c = 'A'; $c <= $column; $c++) {
$data[] = $phpExcel->getActiveSheet()->getCell($c . $i)->getValue();
}
echo "
";
print_r($data);
}
在上述代码中,先if判断Excel表格是否存在,再用require_once引入PHPExcel类库中IOFactory.php这个类,然后使用PHPExcel类库的一个方法载入Excel文件,这里将载入的Excel文件赋值于$phpExcel变量。
然后再将$phpExcel变量通过分别指定相应的方法来获取Excel表格的数目、行数、列数以及通过setActiveSheetIndex(0)方法设置这个表格为默认(0表示默认)。
此时输出表格的数目、行数、列数的结果,通过浏览器访问的结果就出来了。然后我们用for循环遍历出表格的所有内容,再定义一个数组$data来接收这些内容。以上就是为大家分享的内容了,如果大家还是存在不了解的地方,可以留言咨询我们。
本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。
收起阅读 »
MUI实现小米商城视频教程 附代码和笔记
主要课程如下:
mui框架的基本使用
常用组件的使用,包括轮播组件、懒加载、下拉加载和节流函数
小米商城的实现
下载地址:http://www.sucaihuo.com/video/260.html
收起阅读 »
单张拍照 和多张图片选择
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<link href="../css/mui.min.css" rel="stylesheet" />
<link href="../css/iconfont.css" rel="stylesheet" />
<link href="../css/common.css" rel="stylesheet" />
<link href="../css/style.css" rel="stylesheet" />
<script src="../js/mui.min.js"></script>
<script src="../js/public.js"></script>
<script src="../js/common.js"></script>
<script src="../js/vue.min.js"></script>
<script src="../js/canvasResize.js" type="text/javascript" charset="utf-8"></script>
<script src="../js/binaryajax.js" type="text/javascript" charset="utf-8"></script>
<script src="../js/exif.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="take_order">
<div class="bg-y-ffcc00 padding-10 wxrow">
<div class="flex1 b-333">
运单号:xxxxx
</div>
<div class="wxaround" onclick="clicked('barcode_scan.html',true,true)">
<span class="iconfont icon-saoma g-009999 size18"></span>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
地址信息
</div>
<div class='send-view margin-t20'>
<div class='send-tips'>寄</div>
<div class='triangle-left'></div>
<div class='triangle-right'></div>
<div class='import-view' data-type="consigner">
<span class='iconfont icon-daoru margin-r5'></span>
<span class='size12'>导入</span>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>姓名:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consigner-name' v-model="consignerName" placeholder='请输入姓名'></input>
</div>
<div class='wxaround size12'>手机:</div>
<div class='flex3'>
<input type='number' class='send-input consigner-phone' v-model="consignerPhone" placeholder='请输入手机'></input>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>详细地址:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consigner-address' v-model="consignerAddress" placeholder='请输入详细地址'></input>
</div>
<div class='fix-add wxaround select-address' data-type="consigner-address">
<input type="hidden" class="consigner-address-lng" />
<input type="hidden" class="consigner-address-lat" />
<span class='iconfont icon-dingwei size18'></span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>身份证号:</div>
<div class='flex2'>
<input type='text' class='send-input' v-model="consignerIdCard" placeholder='请输入身份证号'></input>
</div>
</div>
</div>
<div class='send-view margin-t30'>
<div class='send-tips collect-tips'>收</div>
<div class='triangle-left collect-triangle-left'></div>
<div class='triangle-right collect-triangle-right'></div>
<div class='import-view' data-type="consignee">
<span class='iconfont icon-daoru margin-r5'></span>
<span class='size12'>导入</span>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>姓名:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consignee-name' v-model="consigneeName" placeholder='请输入姓名'></input>
</div>
<div class='wxaround size12'>手机:</div>
<div class='flex3'>
<input type='number' class='send-input consignee-phone' v-model="consigneePhone" placeholder='请输入手机'></input>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>详细地址:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consignee-address' v-model="consigneeAddress" placeholder='请输入详细地址'></input>
</div>
<div class='fix-add wxaround select-address' data-type="consignee-address">
<input type="hidden" class="consignee-address-lng" />
<input type="hidden" class="consignee-address-lat" />
<span class='iconfont icon-dingwei size18'></span>
</div>
</div>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
物品信息
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>名称</div>
<div class='flex1'>
<input type='text' class='send-input' v-model="goodName" placeholder='请输入名称'></input>
</div>
<div class='wxaround width50 size12'>类型</div>
<div class='flex1 relative'>
<select class="mui-btn send-select">
<option>请选择类型</option>
<option value="item-1">item-1</option>
<option value="item-2">item-2</option>
<option value="item-3">item-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>重量</div>
<div class='flex1 relative'>
<input type='text' class='send-input' placeholder='请输入重量'></input>
<span class="po-down">kg</span>
</div>
<div class='wxaround width50 size12'>数量</div>
<div class='flex1'>
<input type='text' class='send-input' placeholder='请输入名称'></input>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>打包费
</div>
<div class='flex1 relative'>
<select class="mui-btn send-select">
<option>请选择类型</option>
<option value="item-1">item-1</option>
<option value="item-2">item-2</option>
<option value="item-3">item-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
<div class='wxaround width50 size12'>保价费</div>
<div class='flex1 relative'>
<input type='text' class='send-input' placeholder='请输入保价费'></input>
<span class="po-down">元</span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>备注</div>
<div class='flex1 relative'>
<input type='text' class='send-input' placeholder='请输入备注'></input>
</div>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
费用信息
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxcenter width60 size12'>计费模式</div>
<div class='flex1 relative'>
<select class="mui-btn send-select" v-model="billModel">
<option>请选择计费模式</option>
<option value="item-1">计费-1</option>
<option value="item-2">计费-2</option>
<option value="item-3">计费-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxcenter width60 size12'>关闭月结</div>
<div class='flex1'>
<div class="mui-switch " id="mySwitch">
<div class="mui-switch-handle"></div>
</div>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxcenter width60 size12'>费用总计</div>
<div class='flex1'>
<span class="bold">25.50元</span>
</div>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
拍摄照片
</div>
<div class='margin-t10 wxrow img-list'>
<!--<img src="../img/bc-img1.png" class="send-img" />
<img src="../img/ceshi.jpg" class="send-img" />
<img src="../img/head.png" class="send-img" />
<img src="../img/head.png" class="send-img" />
<img src="../img/head.png" class="send-img" />
<img src="../img/head.png" class="send-img" />-->
<!--<img id="showImg" src="../img/head.png" class="send-img" />-->
<div class="send-img add-img" onclick="captureImage()">
<div class="send-img-choose-inside wxaround">
<span class="iconfont icon-tubiao_huabanfuben size20 b-999"></span>
</div>
</div>
</div>
</div>
<div class="padding-10">
<button type="button" class="btn-take">下单</button>
</div>
</div>
<script>
mui.init();
function getDefaultData() {
return {
//寄件人
consignerName: '',
consignerPhone: '',
consignerAddress: '',
consignerIdCard: '',
//收件人
consigneeName: '',
consigneePhone: '',
consigneeAddress: '',
//物品信息
goodName: '',
goodType: '',
goodWeight: '',
goodAmount: '',
goodPack: '',
goodOffer: '',
goodRemark: '',
billModel: ''
}
}
let take_order = new Vue({
el: '#take_order',
data: getDefaultData(),
methods: {
resetData: function() { //重置数据
Object.assign(this.$data, getDefaultData());
}
}
});
function clearView() {
mui.plusReady(function() {
var view = plus.nativeObj.View.getViewById('view');
var view1 = plus.nativeObj.View.getViewById('view1');
if(view) {
view.close();
view1.close();
}
})
}
//导入地址信息
function importInfo(t, n, p, d) {
if(t == 'consigner') {
take_order.consignerName = n;
take_order.consignerPhone = p
take_order.consignerAddress = d;
}
if(t == 'consignee') {
take_order.consigneeName = n;
take_order.consigneePhone = p
take_order.consigneeAddress = d;
}
}
function scaned(t, r, f) {
console.log(t)
console.log(r)
console.log(f)
if(!f || f == 'null') {
img.src = '../img/barcode.png';
} else {
plus.io.resolveLocalFileSystemURL(f, function(entry) {
img.src = entry.toLocalURL();
});
// img.src = 'http://localhost:8020/'+f;
}
}
let maxNum = 9;
let imgTotalNum = 0;
let imgList = null;
// 拍照
function captureImage() {
imgList = ddsd.qsa('.send-img').length - 1;
imgTotalNum = maxNum - imgList;
let bts = [{
title: "拍照",
style: "destructive"
}, {
title: "从相册选择"
}];
plus.nativeUI.actionSheet({
title: "上传拍摄图片",
cancel: "取消",
buttons: bts
},
function(e) {
if(e.index == 1) {
let cmr = plus.camera.getCamera();
cmr.captureImage(function(path) {
plus.io.resolveLocalFileSystemURL(path, function(entry) {
showImg(entry.toLocalURL());
ddsd.qs('.send-img').style.height = ddsd.qs('.add-img').offsetWidth - 2 + 'px';
}, function(e) {
ddsd.toast('读取拍照文件错误:' + e.message);
});
},
function(error) {
ddsd.toast("失败: " + error.message);
}, {
filename: '_doc/camera/',
index: 1
}
);
} else if(e.index == 2) {
plus.gallery.pick(function(e) {
for(var i in e.files) {
showImg(e.files[i]);
}
}, function(e) {
console.log("取消选择图片");
}, {
filter: "image",
multiple: true,
system: false,
maximum: imgTotalNum,
onmaxed: function() {
plus.nativeUI.toast('最多可以选择'+ imgTotalNum +'张图片')
}
});
}
}
);
}
// 添加播放项
function createItem(entry) {
let img = document.createElement('img');
img.className = 'send-img';
img.src = entry.toLocalURL();
ddsd.qs('.img-list').insertBefore(img, ddsd.qs('.img-list').firstChild);
}
var f1 = new Array();
let previewImageList = [];
function showImg(url) {
plus.nativeUI.showWaiting( "加载中..." );
if ((imgList - 1) > 0) {
imgTotalNum = imgTotalNum - (imgList - 1);
}
// 兼容以“file:”开头的情况
if(0 != url.toString().indexOf("file://")) {
url = "file://" + url;
}
var _div_ = ddsd.qs('.img-list');
var _img_ = new Image();
_img_.src = url; // 传过来的图片路径在这里用。
_img_.className = 'send-img';
_img_.onclick = function() {
console.log(f1)
plus.nativeUI.previewImage(previewImageList,{
current:0,
loop:true
});
};
_img_.onload = function() {
var tmph = _img_.height;
var tmpw = _img_.width;
var isHengTu = tmpw > tmph;
var max = Math.max(tmpw, tmph);
var min = Math.min(tmpw, tmph);
var bili = min / max;
if(max > 1200) {
max = 1200;
min = Math.floor(bili * max);
}
tmph = isHengTu ? min : max;
tmpw = isHengTu ? max : min;
_img_.style.height = ddsd.qs('.add-img').offsetWidth - 2 + 'px';
_img_.onload = null;
plus.io.resolveLocalFileSystemURL(url, function(entry) {
entry.file(function(file) {
ddsd.log(file)
canvasResize(file, {
width: tmpw,
height: tmph,
crop: false,
quality: 50, //压缩质量
rotate: 0,
callback: function(data, width, height) {
f1.push(data);
_img_.src = data;
_div_.appendChild(_img_);
previewImageList.push(file.fullPath)
if ((ddsd.qsa('.send-img').length - 1) == 9) {
ddsd.qs('.add-img').style.display = 'none';
}
plus.nativeUI.closeWaiting();
}
});
});
},
function(e) {
plus.nativeUI.closeWaiting();
console.log(e.message);
});
};
};
mui.plusReady(function() {
var img = null;
function update(t, r, f) {
outSet('扫描成功:');
outLine(t);
outLine(r);
outLine('\n图片地址:' + f);
if(!f || f == 'null') {
img.src = '../img/barcode.png';
} else {
plus.io.resolveLocalFileSystemURL(f, function(entry) {
img.src = entry.toLocalURL();
});
//img.src = 'http://localhost:13131/'+f;
}
}
document.getElementById("mySwitch").addEventListener("toggle", function(event) {
if(event.detail.isActive) {
console.log("你启动了开关");
} else {
console.log("你关闭了开关");
}
})
var alist = document.getElementsByClassName("send-img");
if(alist) {
for(var i = 0; i < alist.length; i++) {
alist[i].style.height = alist[i].offsetWidth + "px";;
}
}
//导入发货信息
mui("body").on('tap', '.import-view', function(e) {
var type = this.dataset.type;
var webview = mui.openWindow({
url: 'search_add.html',
id: 'search_add.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '查询地址', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
},
extras: {
type: type
}
});
})
//获取地址信息
mui("body").on('tap', '.select-address', function(e) {
var address = document.querySelector('.' + this.dataset.type).value;
var type = this.dataset.type;
if('Android' === plus.os.name && navigator.userAgent.indexOf('StreamApp') > 0) {
plus.nativeUI.toast('当前环境暂不支持地图插件');
return;
}
var ws = plus.webview.currentWebview();
var wm = plus.webview.getWebviewById(plus.runtime.appid);
wm && wm.evalJS("preateClear()");
var subpage = mui.openWindow({
url: 'maps_map.html',
id: 'maps_map.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '位置信息', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
},
extras: {
address: address,
type: type
}
});
//页面转场的时候清除掉view。
subpage.addEventListener('loaded', function() {
subpage.show('slide-in-right', 200, function() {
view.clear();
view1.clear();
});
});
})
//下单
mui("body").on('tap', '.btn-take', function() {
// if(!take_order.consignerName.Trim()) {
// ddsd.toast('请输入寄件人姓名');
// return false;
// }
// if(!take_order.consignerPhone.Trim()) {
// ddsd.toast('请输入寄件人电话');
// return false;
// }
// if(!take_order.consignerAddress.Trim()) {
// ddsd.toast('请输入寄件人地址');
// return false;
// }
// if(!take_order.consignerIdCard.Trim()) {
// ddsd.toast('请输入寄件人身份证');
// return false;
// }
// if(!take_order.consigneeName.Trim()) {
// ddsd.toast('请输入收件人姓名');
// return false;
// }
// if(!take_order.consigneePhone.Trim()) {
// ddsd.toast('请输入收件人手机');
// return false;
// }
// if(!take_order.consigneeAddress.Trim()) {
// ddsd.toast('请输入收件人地址');
// return false;
// }
console.log(take_order.billModel)
/* mui.openWindow({
url: 'wait_pay.html',
id: 'wait_pay.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '等待支付', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
}
});*/
})
})
function setAddress() {
mui.plusReady(function() {
var addressJson = plus.storage.getItem('addressJson')
var addressData = JSON.parse(addressJson);
document.querySelector('.' + addressData.type).value = addressData.address;
document.querySelector('.' + addressData.type + '-lng').value = addressData.longitude;
document.querySelector('.' + addressData.type + '-lat').value = addressData.latitude;
})
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<link href="../css/mui.min.css" rel="stylesheet" />
<link href="../css/iconfont.css" rel="stylesheet" />
<link href="../css/common.css" rel="stylesheet" />
<link href="../css/style.css" rel="stylesheet" />
<script src="../js/mui.min.js"></script>
<script src="../js/public.js"></script>
<script src="../js/common.js"></script>
<script src="../js/vue.min.js"></script>
<script src="../js/canvasResize.js" type="text/javascript" charset="utf-8"></script>
<script src="../js/binaryajax.js" type="text/javascript" charset="utf-8"></script>
<script src="../js/exif.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="take_order">
<div class="bg-y-ffcc00 padding-10 wxrow">
<div class="flex1 b-333">
运单号:xxxxx
</div>
<div class="wxaround" onclick="clicked('barcode_scan.html',true,true)">
<span class="iconfont icon-saoma g-009999 size18"></span>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
地址信息
</div>
<div class='send-view margin-t20'>
<div class='send-tips'>寄</div>
<div class='triangle-left'></div>
<div class='triangle-right'></div>
<div class='import-view' data-type="consigner">
<span class='iconfont icon-daoru margin-r5'></span>
<span class='size12'>导入</span>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>姓名:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consigner-name' v-model="consignerName" placeholder='请输入姓名'></input>
</div>
<div class='wxaround size12'>手机:</div>
<div class='flex3'>
<input type='number' class='send-input consigner-phone' v-model="consignerPhone" placeholder='请输入手机'></input>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>详细地址:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consigner-address' v-model="consignerAddress" placeholder='请输入详细地址'></input>
</div>
<div class='fix-add wxaround select-address' data-type="consigner-address">
<input type="hidden" class="consigner-address-lng" />
<input type="hidden" class="consigner-address-lat" />
<span class='iconfont icon-dingwei size18'></span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>身份证号:</div>
<div class='flex2'>
<input type='text' class='send-input' v-model="consignerIdCard" placeholder='请输入身份证号'></input>
</div>
</div>
</div>
<div class='send-view margin-t30'>
<div class='send-tips collect-tips'>收</div>
<div class='triangle-left collect-triangle-left'></div>
<div class='triangle-right collect-triangle-right'></div>
<div class='import-view' data-type="consignee">
<span class='iconfont icon-daoru margin-r5'></span>
<span class='size12'>导入</span>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>姓名:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consignee-name' v-model="consigneeName" placeholder='请输入姓名'></input>
</div>
<div class='wxaround size12'>手机:</div>
<div class='flex3'>
<input type='number' class='send-input consignee-phone' v-model="consigneePhone" placeholder='请输入手机'></input>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround size12'>详细地址:</div>
<div class='flex2 padding-r10'>
<input type='text' class='send-input consignee-address' v-model="consigneeAddress" placeholder='请输入详细地址'></input>
</div>
<div class='fix-add wxaround select-address' data-type="consignee-address">
<input type="hidden" class="consignee-address-lng" />
<input type="hidden" class="consignee-address-lat" />
<span class='iconfont icon-dingwei size18'></span>
</div>
</div>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
物品信息
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>名称</div>
<div class='flex1'>
<input type='text' class='send-input' v-model="goodName" placeholder='请输入名称'></input>
</div>
<div class='wxaround width50 size12'>类型</div>
<div class='flex1 relative'>
<select class="mui-btn send-select">
<option>请选择类型</option>
<option value="item-1">item-1</option>
<option value="item-2">item-2</option>
<option value="item-3">item-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>重量</div>
<div class='flex1 relative'>
<input type='text' class='send-input' placeholder='请输入重量'></input>
<span class="po-down">kg</span>
</div>
<div class='wxaround width50 size12'>数量</div>
<div class='flex1'>
<input type='text' class='send-input' placeholder='请输入名称'></input>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>打包费
</div>
<div class='flex1 relative'>
<select class="mui-btn send-select">
<option>请选择类型</option>
<option value="item-1">item-1</option>
<option value="item-2">item-2</option>
<option value="item-3">item-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
<div class='wxaround width50 size12'>保价费</div>
<div class='flex1 relative'>
<input type='text' class='send-input' placeholder='请输入保价费'></input>
<span class="po-down">元</span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxaround width50 size12'>备注</div>
<div class='flex1 relative'>
<input type='text' class='send-input' placeholder='请输入备注'></input>
</div>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
费用信息
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxcenter width60 size12'>计费模式</div>
<div class='flex1 relative'>
<select class="mui-btn send-select" v-model="billModel">
<option>请选择计费模式</option>
<option value="item-1">计费-1</option>
<option value="item-2">计费-2</option>
<option value="item-3">计费-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxcenter width60 size12'>关闭月结</div>
<div class='flex1'>
<div class="mui-switch " id="mySwitch">
<div class="mui-switch-handle"></div>
</div>
</div>
</div>
<div class='margin-t20 wxrow b-333'>
<div class='wxcenter width60 size12'>费用总计</div>
<div class='flex1'>
<span class="bold">25.50元</span>
</div>
</div>
</div>
<div class="bg-w-fff padding-10 margin-t10">
<div class="bold">
拍摄照片
</div>
<div class='margin-t10 wxrow img-list'>
<!--<img src="../img/bc-img1.png" class="send-img" />
<img src="../img/ceshi.jpg" class="send-img" />
<img src="../img/head.png" class="send-img" />
<img src="../img/head.png" class="send-img" />
<img src="../img/head.png" class="send-img" />
<img src="../img/head.png" class="send-img" />-->
<!--<img id="showImg" src="../img/head.png" class="send-img" />-->
<div class="send-img add-img" onclick="captureImage()">
<div class="send-img-choose-inside wxaround">
<span class="iconfont icon-tubiao_huabanfuben size20 b-999"></span>
</div>
</div>
</div>
</div>
<div class="padding-10">
<button type="button" class="btn-take">下单</button>
</div>
</div>
<script>
mui.init();
function getDefaultData() {
return {
//寄件人
consignerName: '',
consignerPhone: '',
consignerAddress: '',
consignerIdCard: '',
//收件人
consigneeName: '',
consigneePhone: '',
consigneeAddress: '',
//物品信息
goodName: '',
goodType: '',
goodWeight: '',
goodAmount: '',
goodPack: '',
goodOffer: '',
goodRemark: '',
billModel: ''
}
}
let take_order = new Vue({
el: '#take_order',
data: getDefaultData(),
methods: {
resetData: function() { //重置数据
Object.assign(this.$data, getDefaultData());
}
}
});
function clearView() {
mui.plusReady(function() {
var view = plus.nativeObj.View.getViewById('view');
var view1 = plus.nativeObj.View.getViewById('view1');
if(view) {
view.close();
view1.close();
}
})
}
//导入地址信息
function importInfo(t, n, p, d) {
if(t == 'consigner') {
take_order.consignerName = n;
take_order.consignerPhone = p
take_order.consignerAddress = d;
}
if(t == 'consignee') {
take_order.consigneeName = n;
take_order.consigneePhone = p
take_order.consigneeAddress = d;
}
}
function scaned(t, r, f) {
console.log(t)
console.log(r)
console.log(f)
if(!f || f == 'null') {
img.src = '../img/barcode.png';
} else {
plus.io.resolveLocalFileSystemURL(f, function(entry) {
img.src = entry.toLocalURL();
});
// img.src = 'http://localhost:8020/'+f;
}
}
let maxNum = 9;
let imgTotalNum = 0;
let imgList = null;
// 拍照
function captureImage() {
imgList = ddsd.qsa('.send-img').length - 1;
imgTotalNum = maxNum - imgList;
let bts = [{
title: "拍照",
style: "destructive"
}, {
title: "从相册选择"
}];
plus.nativeUI.actionSheet({
title: "上传拍摄图片",
cancel: "取消",
buttons: bts
},
function(e) {
if(e.index == 1) {
let cmr = plus.camera.getCamera();
cmr.captureImage(function(path) {
plus.io.resolveLocalFileSystemURL(path, function(entry) {
showImg(entry.toLocalURL());
ddsd.qs('.send-img').style.height = ddsd.qs('.add-img').offsetWidth - 2 + 'px';
}, function(e) {
ddsd.toast('读取拍照文件错误:' + e.message);
});
},
function(error) {
ddsd.toast("失败: " + error.message);
}, {
filename: '_doc/camera/',
index: 1
}
);
} else if(e.index == 2) {
plus.gallery.pick(function(e) {
for(var i in e.files) {
showImg(e.files[i]);
}
}, function(e) {
console.log("取消选择图片");
}, {
filter: "image",
multiple: true,
system: false,
maximum: imgTotalNum,
onmaxed: function() {
plus.nativeUI.toast('最多可以选择'+ imgTotalNum +'张图片')
}
});
}
}
);
}
// 添加播放项
function createItem(entry) {
let img = document.createElement('img');
img.className = 'send-img';
img.src = entry.toLocalURL();
ddsd.qs('.img-list').insertBefore(img, ddsd.qs('.img-list').firstChild);
}
var f1 = new Array();
let previewImageList = [];
function showImg(url) {
plus.nativeUI.showWaiting( "加载中..." );
if ((imgList - 1) > 0) {
imgTotalNum = imgTotalNum - (imgList - 1);
}
// 兼容以“file:”开头的情况
if(0 != url.toString().indexOf("file://")) {
url = "file://" + url;
}
var _div_ = ddsd.qs('.img-list');
var _img_ = new Image();
_img_.src = url; // 传过来的图片路径在这里用。
_img_.className = 'send-img';
_img_.onclick = function() {
console.log(f1)
plus.nativeUI.previewImage(previewImageList,{
current:0,
loop:true
});
};
_img_.onload = function() {
var tmph = _img_.height;
var tmpw = _img_.width;
var isHengTu = tmpw > tmph;
var max = Math.max(tmpw, tmph);
var min = Math.min(tmpw, tmph);
var bili = min / max;
if(max > 1200) {
max = 1200;
min = Math.floor(bili * max);
}
tmph = isHengTu ? min : max;
tmpw = isHengTu ? max : min;
_img_.style.height = ddsd.qs('.add-img').offsetWidth - 2 + 'px';
_img_.onload = null;
plus.io.resolveLocalFileSystemURL(url, function(entry) {
entry.file(function(file) {
ddsd.log(file)
canvasResize(file, {
width: tmpw,
height: tmph,
crop: false,
quality: 50, //压缩质量
rotate: 0,
callback: function(data, width, height) {
f1.push(data);
_img_.src = data;
_div_.appendChild(_img_);
previewImageList.push(file.fullPath)
if ((ddsd.qsa('.send-img').length - 1) == 9) {
ddsd.qs('.add-img').style.display = 'none';
}
plus.nativeUI.closeWaiting();
}
});
});
},
function(e) {
plus.nativeUI.closeWaiting();
console.log(e.message);
});
};
};
mui.plusReady(function() {
var img = null;
function update(t, r, f) {
outSet('扫描成功:');
outLine(t);
outLine(r);
outLine('\n图片地址:' + f);
if(!f || f == 'null') {
img.src = '../img/barcode.png';
} else {
plus.io.resolveLocalFileSystemURL(f, function(entry) {
img.src = entry.toLocalURL();
});
//img.src = 'http://localhost:13131/'+f;
}
}
document.getElementById("mySwitch").addEventListener("toggle", function(event) {
if(event.detail.isActive) {
console.log("你启动了开关");
} else {
console.log("你关闭了开关");
}
})
var alist = document.getElementsByClassName("send-img");
if(alist) {
for(var i = 0; i < alist.length; i++) {
alist[i].style.height = alist[i].offsetWidth + "px";;
}
}
//导入发货信息
mui("body").on('tap', '.import-view', function(e) {
var type = this.dataset.type;
var webview = mui.openWindow({
url: 'search_add.html',
id: 'search_add.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '查询地址', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
},
extras: {
type: type
}
});
})
//获取地址信息
mui("body").on('tap', '.select-address', function(e) {
var address = document.querySelector('.' + this.dataset.type).value;
var type = this.dataset.type;
if('Android' === plus.os.name && navigator.userAgent.indexOf('StreamApp') > 0) {
plus.nativeUI.toast('当前环境暂不支持地图插件');
return;
}
var ws = plus.webview.currentWebview();
var wm = plus.webview.getWebviewById(plus.runtime.appid);
wm && wm.evalJS("preateClear()");
var subpage = mui.openWindow({
url: 'maps_map.html',
id: 'maps_map.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '位置信息', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
},
extras: {
address: address,
type: type
}
});
//页面转场的时候清除掉view。
subpage.addEventListener('loaded', function() {
subpage.show('slide-in-right', 200, function() {
view.clear();
view1.clear();
});
});
})
//下单
mui("body").on('tap', '.btn-take', function() {
// if(!take_order.consignerName.Trim()) {
// ddsd.toast('请输入寄件人姓名');
// return false;
// }
// if(!take_order.consignerPhone.Trim()) {
// ddsd.toast('请输入寄件人电话');
// return false;
// }
// if(!take_order.consignerAddress.Trim()) {
// ddsd.toast('请输入寄件人地址');
// return false;
// }
// if(!take_order.consignerIdCard.Trim()) {
// ddsd.toast('请输入寄件人身份证');
// return false;
// }
// if(!take_order.consigneeName.Trim()) {
// ddsd.toast('请输入收件人姓名');
// return false;
// }
// if(!take_order.consigneePhone.Trim()) {
// ddsd.toast('请输入收件人手机');
// return false;
// }
// if(!take_order.consigneeAddress.Trim()) {
// ddsd.toast('请输入收件人地址');
// return false;
// }
console.log(take_order.billModel)
/* mui.openWindow({
url: 'wait_pay.html',
id: 'wait_pay.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '等待支付', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
}
});*/
})
})
function setAddress() {
mui.plusReady(function() {
var addressJson = plus.storage.getItem('addressJson')
var addressData = JSON.parse(addressJson);
document.querySelector('.' + addressData.type).value = addressData.address;
document.querySelector('.' + addressData.type + '-lng').value = addressData.longitude;
document.querySelector('.' + addressData.type + '-lat').value = addressData.latitude;
})
}
</script>
</body>
</html>
收起阅读 »
NFC读取卡片ID
本人小白一枚,在基于@Android_磊子大哥的文章(原文地址)以及网上的一些大神的文章,改了一点自己需要的功能
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<title></title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
var NfcAdapter;
var NdefRecord;
var NdefMessage;
function listenNFCStatus() {
try{
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass('android.content.Intent');
var Activity = plus.android.importClass('android.app.Activity');
var PendingIntent = plus.android.importClass('android.app.PendingIntent');
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
var nfcAdapter = NfcAdapter.getDefaultAdapter(main);
var intent = new Intent(main, main.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
var pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
ndef.addDataType("*/*");
var intentFiltersArray = [ndef];
var techListsArray = [
["android.nfc.tech.IsoDep"],
["android.nfc.tech.NfcA"],
["android.nfc.tech.NfcB"],
["android.nfc.tech.NfcF"],
["android.nfc.tech.Nfcf"],
["android.nfc.tech.NfcV"],
["android.nfc.tech.NdefFormatable"],
["android.nfc.tech.MifareClassic"],
["android.nfc.tech.MifareUltralight"]
];
document.addEventListener("newintent",
function() {
console.error('newintent');
setTimeout(handle_nfc_data1, 1000);
}, false);
document.addEventListener("pause", function(e) {
if (nfcAdapter) {
nfcAdapter.disableForegroundDispatch(main);
console.log('pause');
}
}, false);
document.addEventListener("resume", function(e) {
if (nfcAdapter) {
console.log('resume');
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
}
}, false);
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
}catch(e){
console.error(e);
}
}
function handle_nfc_data1()
{
NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
var main = plus.android.runtimeMainActivity();
var intent = main.getIntent();
console.log("action type:" + intent.getAction());
if("android.nfc.action.TECH_DISCOVERED" == intent.getAction()){
if(readyWriteData){
__write(intent);
readyWriteData = false;
}else if(readyRead){
__read(intent);
readyRead = false;
}
}
}
function showToast(msg){
plus.nativeUI.toast(msg);
}
function __write(intent){
try{
waiting.setTitle('请勿移开标签\n正在写入...');
var text = document.getElementById('text').value;
console.log("text=" + text);
var textBytes = plus.android.invoke(text,"getBytes");
var textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
plus.android.invoke("text/plain","getBytes"), plus.android.invoke("","getBytes"), textBytes);
var message = new NdefMessage([textRecord]);
var Ndef = plus.android.importClass('android.nfc.tech.Ndef');
var NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');
var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
var ndef = Ndef.get(tag);
if (ndef != null) {
var size = message.toByteArray().length;
console.log("size=" + size);
ndef.connect();
if (!ndef.isWritable()) {
showToast("tag不允许写入");
waiting.close();
return ;
}
if (ndef.getMaxSize() < size) {
showToast("文件大小超出容量");
waiting.close();
return ;
}
ndef.writeNdefMessage(message);
waiting.close();
showToast("写入数据成功.");
return ;
} else {
var format = NdefFormatable.get(tag);
if (format != null) {
try {
format.connect();
format.format(message);
showToast("格式化tag并且写入message");
waiting.close();
return ;
} catch (e) {
showToast("格式化tag失败.");
waiting.close();
return ;
}
} else {
showToast("Tag不支持NDEF");
waiting.close();
return ;
}
}
}catch(e){
console.log("error=" + e);
waiting.close();
alert('写入失败');
}
}
function __read(intent){
try{
var content = "";
waiting.setTitle('请勿移开标签\n正在读取数据...');
var tag = plus.android.importClass("android.nfc.Tag");
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
var bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
console.log("bytesId:"+(bytesId));
waiting.close();
content +="卡片字节数组ID:"+tag.getId()+"<br/>";
content +="卡片16进制ID:"+ bytesToHexString(tag.getId())+"<br/>";
var tagid = reverseTwo(bytesToHexString(tag.getId()));
content +="卡片16进制翻转ID:"+tagid+"<br/>";
content +="卡片10进制卡号:"+parseInt(tagid, 16)+"<br/>";
$("#content").html(content);
}catch(e){
alert(e);
//TODO handle the exception
}
}
function bytesToHexString(inarray){
var i, j, x;
var hex = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
"B", "C", "D", "E", "F" ];
var out = "";
for (j = 0; j < inarray.length; ++j) {
x = parseInt(inarray[j]) & 0xff;
i = (x >> 4) & 0x0f;
out += hex[i];
i = x & 0x0f;
out += hex[i];
}
return out;
}
function reverseTwo(str)
{
var str1 = "";
for(var i = 1; i <= str.length; i++){
str1 +=str[i-1];
if(i%2==0){
if(i == str.length){
break;
}
str1+=":";
}
}
var str2 = "";
for(var i = str1.split(":").length-1; i >= 0 ; i--){
str2+= str1.split(":")[i];
}
return str2;
}
document.addEventListener('plusready',listenNFCStatus,false);
var waiting ;
var readyWriteData = false;
var readyRead = false;
function writeData(){
var textEle = document.getElementById('text');
if(!textEle.value){
alert('请输入要写入的内容');
return;
}
readyWriteData = true;
waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");
}
function readData(){
readyRead = true;
waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");
}
</script>
<style>
button{
width: 50%;
height: 50px;
}
</style>
</head>
<body>
输入要写入的内容:<br/><textarea id="text">姓名:张二蛋年龄:29地址:北京海淀区</textarea><br/>
<button onclick="writeData()">写入</button>
<button style="position: absolute; bottom: 100px; right: 100px;" onclick="readData()">读取</button><br/>
读取的内容:
<div id="content"/>
</body>
</html>
manifest.json 模块权限配置勾选了NFC
避免打包之后刷卡会闪退
本人小白一枚,在基于@Android_磊子大哥的文章(原文地址)以及网上的一些大神的文章,改了一点自己需要的功能
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<title></title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
var NfcAdapter;
var NdefRecord;
var NdefMessage;
function listenNFCStatus() {
try{
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass('android.content.Intent');
var Activity = plus.android.importClass('android.app.Activity');
var PendingIntent = plus.android.importClass('android.app.PendingIntent');
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
var nfcAdapter = NfcAdapter.getDefaultAdapter(main);
var intent = new Intent(main, main.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
var pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
ndef.addDataType("*/*");
var intentFiltersArray = [ndef];
var techListsArray = [
["android.nfc.tech.IsoDep"],
["android.nfc.tech.NfcA"],
["android.nfc.tech.NfcB"],
["android.nfc.tech.NfcF"],
["android.nfc.tech.Nfcf"],
["android.nfc.tech.NfcV"],
["android.nfc.tech.NdefFormatable"],
["android.nfc.tech.MifareClassic"],
["android.nfc.tech.MifareUltralight"]
];
document.addEventListener("newintent",
function() {
console.error('newintent');
setTimeout(handle_nfc_data1, 1000);
}, false);
document.addEventListener("pause", function(e) {
if (nfcAdapter) {
nfcAdapter.disableForegroundDispatch(main);
console.log('pause');
}
}, false);
document.addEventListener("resume", function(e) {
if (nfcAdapter) {
console.log('resume');
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
}
}, false);
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
}catch(e){
console.error(e);
}
}
function handle_nfc_data1()
{
NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
var main = plus.android.runtimeMainActivity();
var intent = main.getIntent();
console.log("action type:" + intent.getAction());
if("android.nfc.action.TECH_DISCOVERED" == intent.getAction()){
if(readyWriteData){
__write(intent);
readyWriteData = false;
}else if(readyRead){
__read(intent);
readyRead = false;
}
}
}
function showToast(msg){
plus.nativeUI.toast(msg);
}
function __write(intent){
try{
waiting.setTitle('请勿移开标签\n正在写入...');
var text = document.getElementById('text').value;
console.log("text=" + text);
var textBytes = plus.android.invoke(text,"getBytes");
var textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
plus.android.invoke("text/plain","getBytes"), plus.android.invoke("","getBytes"), textBytes);
var message = new NdefMessage([textRecord]);
var Ndef = plus.android.importClass('android.nfc.tech.Ndef');
var NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');
var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
var ndef = Ndef.get(tag);
if (ndef != null) {
var size = message.toByteArray().length;
console.log("size=" + size);
ndef.connect();
if (!ndef.isWritable()) {
showToast("tag不允许写入");
waiting.close();
return ;
}
if (ndef.getMaxSize() < size) {
showToast("文件大小超出容量");
waiting.close();
return ;
}
ndef.writeNdefMessage(message);
waiting.close();
showToast("写入数据成功.");
return ;
} else {
var format = NdefFormatable.get(tag);
if (format != null) {
try {
format.connect();
format.format(message);
showToast("格式化tag并且写入message");
waiting.close();
return ;
} catch (e) {
showToast("格式化tag失败.");
waiting.close();
return ;
}
} else {
showToast("Tag不支持NDEF");
waiting.close();
return ;
}
}
}catch(e){
console.log("error=" + e);
waiting.close();
alert('写入失败');
}
}
function __read(intent){
try{
var content = "";
waiting.setTitle('请勿移开标签\n正在读取数据...');
var tag = plus.android.importClass("android.nfc.Tag");
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
var bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
console.log("bytesId:"+(bytesId));
waiting.close();
content +="卡片字节数组ID:"+tag.getId()+"<br/>";
content +="卡片16进制ID:"+ bytesToHexString(tag.getId())+"<br/>";
var tagid = reverseTwo(bytesToHexString(tag.getId()));
content +="卡片16进制翻转ID:"+tagid+"<br/>";
content +="卡片10进制卡号:"+parseInt(tagid, 16)+"<br/>";
$("#content").html(content);
}catch(e){
alert(e);
//TODO handle the exception
}
}
function bytesToHexString(inarray){
var i, j, x;
var hex = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
"B", "C", "D", "E", "F" ];
var out = "";
for (j = 0; j < inarray.length; ++j) {
x = parseInt(inarray[j]) & 0xff;
i = (x >> 4) & 0x0f;
out += hex[i];
i = x & 0x0f;
out += hex[i];
}
return out;
}
function reverseTwo(str)
{
var str1 = "";
for(var i = 1; i <= str.length; i++){
str1 +=str[i-1];
if(i%2==0){
if(i == str.length){
break;
}
str1+=":";
}
}
var str2 = "";
for(var i = str1.split(":").length-1; i >= 0 ; i--){
str2+= str1.split(":")[i];
}
return str2;
}
document.addEventListener('plusready',listenNFCStatus,false);
var waiting ;
var readyWriteData = false;
var readyRead = false;
function writeData(){
var textEle = document.getElementById('text');
if(!textEle.value){
alert('请输入要写入的内容');
return;
}
readyWriteData = true;
waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");
}
function readData(){
readyRead = true;
waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");
}
</script>
<style>
button{
width: 50%;
height: 50px;
}
</style>
</head>
<body>
输入要写入的内容:<br/><textarea id="text">姓名:张二蛋年龄:29地址:北京海淀区</textarea><br/>
<button onclick="writeData()">写入</button>
<button style="position: absolute; bottom: 100px; right: 100px;" onclick="readData()">读取</button><br/>
读取的内容:
<div id="content"/>
</body>
</html>
manifest.json 模块权限配置勾选了NFC
避免打包之后刷卡会闪退

PDA终端扫描实现
以下方法都是非原生方式实现
Javascript获取扫码结果实现
document.onkeydown=function(e){
//webview不需要兼容ie
console.log(e.keyCode)
}
该方法需要判断按键和间隔输入情况,用户可能在扫码的时候有其他按键等误操作,所以不建议用来进行获取扫码结果。
Native.js监听广播消息实现
参考论坛 回答
function plusReady() {
var main = plus.android.runtimeMainActivity();//获取activity
var context = plus.android.importClass('android.content.Context'); //上下文
var receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver',{
onReceive : doReceive });
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
var Intent = plus.android.importClass('android.content.Intent');
var filter = new IntentFilter();
filter.addAction("com.zkc.scancode");//监听扫描
main.registerReceiver(receiver,filter);//注册监听
function doReceive(context, intent) {
plus.android.importClass(intent);//通过intent实例引入intent类,方便以后的‘.’操作
var Number = intent.getStringExtra("code");
console.log(Number);
main.unregisterReceiver(receiver);//取消监听
}
}
销邦X8扫描枪
我这里使用的是销邦科技X8扫描设备,由于设备不一样导致文章中的代码不能直接使用,需要配置监听的数据才能连接。搜索销邦官网获取对应开发包下载
注意设置内勾选开启扫描,选择输入模式API:
打开开发说明查看参数:
代码对应修改如下:
···
filter.addAction("com.android.server.scannerservice.broadcast");//监听扫描
···
intent.getStringExtra("scannerdata");//返回结果
···
原代码实现的是扫码完成就取消监听这样不符合实际业务(多次扫描),但是不取消监听用同时有打开新的页面,这时会发现之前的页面还在监听扫描,当然在打开新页面的时候进行取消监听,但是当用户从新页面返回之前的页面时又需要重启监听,各种条件判断写出了比较麻烦。
这里采用的是接受扫描结果时判断是否是当前显示页面。首先在打开页面时把页面id存储到本地,并且重写back:
function pageInit(){
var _self = plus.webview.currentWebview()
localStorage.setItem('WEBVIEW_ID', _self.id)
mui.back = function() {
localStorage.setItem('WEBVIEW_ID', _self.opener().id)
_self.close()
}
}
然后判断页面id:
function scan(callback){
var main = plus.android.runtimeMainActivity(); //获取activity
var receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
onReceive: function(context, intent){//实现onReceiver回调函数
if(plus.webview.currentWebview().id != localStorage.getItem(util.config.WEBVIEW_ID)) return
callback(intent.getStringExtra('scannerdata'))
}
});
var IntentFilter = plus.android.importClass('android.content.IntentFilter');//引入过滤器
var Intent = plus.android.importClass('android.content.Intent');
var filter = new IntentFilter();
filter.addAction('com.android.server.scannerservice.broadcast'); //监听扫码广播
main.registerReceiver(receiver, filter); //注册监听
}
页面使用:
mui.plusReady(function () {
pageInit()
setTimeout(function(){
scan(function(code){
console.log('扫描结果:'+code)
})
},300)
})
注意:在HBuilder控制台没有调试信息,需要在webview调试窗口中才能看到打印信息。另建议在plusReady中延迟执行scan()。
霍尼韦尔扫描枪
首先需要在设备上去设置监听的对象名(我这里设置成和销邦设备一样的com.android.server.scannerservice.broadcast),接受参数的时候再判断一下设备plus.device.model进行切换接受返回结果的对象名:
scan: function(callback){
var main = plus.android.runtimeMainActivity(); //获取activity
var context = plus.android.importClass('android.content.Context'); //上下文
var receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
onReceive: function(context, intent){//实现onReceiver回调函数
if(plus.webview.currentWebview().id != localStorage.getItem(util.config.WEBVIEW_ID)) return
var _key = plus.device.model == 'EDA50K' ? 'data' : 'scannerdata';
callback(intent.getStringExtra(_key))
}
});
var IntentFilter = plus.android.importClass('android.content.IntentFilter');//引入过滤器
var Intent = plus.android.importClass('android.content.Intent');
var filter = new IntentFilter();
filter.addAction('com.android.server.scannerservice.broadcast'); //监听扫码广播
main.registerReceiver(receiver, filter); //注册监听
}
以下方法都是非原生方式实现
Javascript获取扫码结果实现
document.onkeydown=function(e){
//webview不需要兼容ie
console.log(e.keyCode)
}
该方法需要判断按键和间隔输入情况,用户可能在扫码的时候有其他按键等误操作,所以不建议用来进行获取扫码结果。
Native.js监听广播消息实现
参考论坛 回答
function plusReady() {
var main = plus.android.runtimeMainActivity();//获取activity
var context = plus.android.importClass('android.content.Context'); //上下文
var receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver',{
onReceive : doReceive });
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
var Intent = plus.android.importClass('android.content.Intent');
var filter = new IntentFilter();
filter.addAction("com.zkc.scancode");//监听扫描
main.registerReceiver(receiver,filter);//注册监听
function doReceive(context, intent) {
plus.android.importClass(intent);//通过intent实例引入intent类,方便以后的‘.’操作
var Number = intent.getStringExtra("code");
console.log(Number);
main.unregisterReceiver(receiver);//取消监听
}
}
销邦X8扫描枪
我这里使用的是销邦科技X8扫描设备,由于设备不一样导致文章中的代码不能直接使用,需要配置监听的数据才能连接。搜索销邦官网获取对应开发包下载
注意设置内勾选开启扫描,选择输入模式API:
打开开发说明查看参数:
代码对应修改如下:
···
filter.addAction("com.android.server.scannerservice.broadcast");//监听扫描
···
intent.getStringExtra("scannerdata");//返回结果
···
原代码实现的是扫码完成就取消监听这样不符合实际业务(多次扫描),但是不取消监听用同时有打开新的页面,这时会发现之前的页面还在监听扫描,当然在打开新页面的时候进行取消监听,但是当用户从新页面返回之前的页面时又需要重启监听,各种条件判断写出了比较麻烦。
这里采用的是接受扫描结果时判断是否是当前显示页面。首先在打开页面时把页面id存储到本地,并且重写back:
function pageInit(){
var _self = plus.webview.currentWebview()
localStorage.setItem('WEBVIEW_ID', _self.id)
mui.back = function() {
localStorage.setItem('WEBVIEW_ID', _self.opener().id)
_self.close()
}
}
然后判断页面id:
function scan(callback){
var main = plus.android.runtimeMainActivity(); //获取activity
var receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
onReceive: function(context, intent){//实现onReceiver回调函数
if(plus.webview.currentWebview().id != localStorage.getItem(util.config.WEBVIEW_ID)) return
callback(intent.getStringExtra('scannerdata'))
}
});
var IntentFilter = plus.android.importClass('android.content.IntentFilter');//引入过滤器
var Intent = plus.android.importClass('android.content.Intent');
var filter = new IntentFilter();
filter.addAction('com.android.server.scannerservice.broadcast'); //监听扫码广播
main.registerReceiver(receiver, filter); //注册监听
}
页面使用:
mui.plusReady(function () {
pageInit()
setTimeout(function(){
scan(function(code){
console.log('扫描结果:'+code)
})
},300)
})
注意:在HBuilder控制台没有调试信息,需要在webview调试窗口中才能看到打印信息。另建议在plusReady中延迟执行scan()。
霍尼韦尔扫描枪
首先需要在设备上去设置监听的对象名(我这里设置成和销邦设备一样的com.android.server.scannerservice.broadcast),接受参数的时候再判断一下设备plus.device.model进行切换接受返回结果的对象名:
scan: function(callback){
var main = plus.android.runtimeMainActivity(); //获取activity
var context = plus.android.importClass('android.content.Context'); //上下文
var receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
onReceive: function(context, intent){//实现onReceiver回调函数
if(plus.webview.currentWebview().id != localStorage.getItem(util.config.WEBVIEW_ID)) return
var _key = plus.device.model == 'EDA50K' ? 'data' : 'scannerdata';
callback(intent.getStringExtra(_key))
}
});
var IntentFilter = plus.android.importClass('android.content.IntentFilter');//引入过滤器
var Intent = plus.android.importClass('android.content.Intent');
var filter = new IntentFilter();
filter.addAction('com.android.server.scannerservice.broadcast'); //监听扫码广播
main.registerReceiver(receiver, filter); //注册监听
}
收起阅读 »

快递连续扫码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<link href="../css/mui.min.css" rel="stylesheet" />
<link href="../css/iconfont.css" rel="stylesheet" />
<link href="../css/common.css" rel="stylesheet" />
<link href="../css/style.css" rel="stylesheet" />
<script src="../js/mui.min.js"></script>
<script src="../js/public.js"></script>
<style>
#bcid {
height: 280px;
width:300px;
}
</style>
</head>
<body>
<div class="scan-img-div" style="display: none;">
<div id="bcid" >
</div>
</div>
<div class="padding-lr20">
<div class="scan-result-div">
<div class="wxrow">
<div class='wxcenter padding-l5 width60 size12 bold'>下一站:</div>
<div class='flex1 relative'>
<select class="mui-btn send-select">
<option>请选择下一站</option>
<option value="item-1">item-1</option>
<option value="item-2">item-2</option>
<option value="item-3">item-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
</div>
<div class="wxrow padding-lr5 padding-b10 margin-b10 margin-t30 bor-b-g2 size12">
<div class="flex1 bold">扫描结果</div>
<div class="">
<span class="b-999">票数:</span>
<span class="g-009999">8xx</span>
</div>
</div>
<div class="wxrow margin-t10 padding-lr10">
<div class="b-333 margin-r15">589078476897438xxx</div>
<div class="width40 wxaround">
<span class="iconfont icon-cha r-ff0000"></span>
</div>
</div>
<div class="wxrow margin-t10 padding-lr10">
<div class="b-333 margin-r15">589078476897438xxx</div>
<div class="width40 wxaround margin-l40">
<span class="iconfont icon-cha r-ff0000"></span>
</div>
</div>
</div>
</div>
<div class="fix-b-scan wxrow">
<div class="flex1 scan-btn bg-o-ff6600" id="scan-go">确认出仓</div>
<div class="flex2 scan-btn bg-b-383838" onclick="openScan()">扫描</div>
</div>
<script type="text/javascript">
console.log(1)
mui.init()
let scan = null;
function openScan() {
ddsd.qs('.scan-img-div').style.display = 'block'
scan = new plus.barcode.Barcode('bcid', [
plus.barcode.EAN13,
plus.barcode.EAN8,
plus.barcode.CODE39,
plus.barcode.CODE93,
plus.barcode.CODE128
], {
top:'1000px',
left:'0px',
width: '100%',
height: '100px',
position: 'static',
frameColor: '#00FF00',
scanbarColor: '#00FF00'
});
scan.onmarked = onmarked;
scan.start();
}
mui.plusReady(function() {
function onmarked(type, result) {
var text = '未知: ';
switch(type) {
case plus.barcode.QR:
text = 'QR: ';
break;
case plus.barcode.EAN13:
text = 'EAN13: ';
break;
case plus.barcode.EAN8:
text = 'EAN8: ';
break;
case plus.barcode.CODE39:
text = 'CODE39: ';
break;
case plus.barcode.CODE93:
text = 'CODE93: ';
break;
case plus.barcode.CODE128:
text = 'CODE128: ';
break;
}
console.log(text + result);
if(result) {
console.log(result)
// scan.close();
// window.location.reload();
scan.cancel();
setTimeout(() => {
scan.start();
},1000)
}
}
mui("body").on('tap', '#scan-go', function() {
mui.openWindow({
url: 'scan_success.html',
id: 'scan_success.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '出仓成功', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
}
});
})
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<link href="../css/mui.min.css" rel="stylesheet" />
<link href="../css/iconfont.css" rel="stylesheet" />
<link href="../css/common.css" rel="stylesheet" />
<link href="../css/style.css" rel="stylesheet" />
<script src="../js/mui.min.js"></script>
<script src="../js/public.js"></script>
<style>
#bcid {
height: 280px;
width:300px;
}
</style>
</head>
<body>
<div class="scan-img-div" style="display: none;">
<div id="bcid" >
</div>
</div>
<div class="padding-lr20">
<div class="scan-result-div">
<div class="wxrow">
<div class='wxcenter padding-l5 width60 size12 bold'>下一站:</div>
<div class='flex1 relative'>
<select class="mui-btn send-select">
<option>请选择下一站</option>
<option value="item-1">item-1</option>
<option value="item-2">item-2</option>
<option value="item-3">item-3</option>
<option value="item-4">item-4</option>
<option value="item-5">item-5</option>
</select>
<span class="iconfont icon-xiajiantou po-down"></span>
</div>
</div>
<div class="wxrow padding-lr5 padding-b10 margin-b10 margin-t30 bor-b-g2 size12">
<div class="flex1 bold">扫描结果</div>
<div class="">
<span class="b-999">票数:</span>
<span class="g-009999">8xx</span>
</div>
</div>
<div class="wxrow margin-t10 padding-lr10">
<div class="b-333 margin-r15">589078476897438xxx</div>
<div class="width40 wxaround">
<span class="iconfont icon-cha r-ff0000"></span>
</div>
</div>
<div class="wxrow margin-t10 padding-lr10">
<div class="b-333 margin-r15">589078476897438xxx</div>
<div class="width40 wxaround margin-l40">
<span class="iconfont icon-cha r-ff0000"></span>
</div>
</div>
</div>
</div>
<div class="fix-b-scan wxrow">
<div class="flex1 scan-btn bg-o-ff6600" id="scan-go">确认出仓</div>
<div class="flex2 scan-btn bg-b-383838" onclick="openScan()">扫描</div>
</div>
<script type="text/javascript">
console.log(1)
mui.init()
let scan = null;
function openScan() {
ddsd.qs('.scan-img-div').style.display = 'block'
scan = new plus.barcode.Barcode('bcid', [
plus.barcode.EAN13,
plus.barcode.EAN8,
plus.barcode.CODE39,
plus.barcode.CODE93,
plus.barcode.CODE128
], {
top:'1000px',
left:'0px',
width: '100%',
height: '100px',
position: 'static',
frameColor: '#00FF00',
scanbarColor: '#00FF00'
});
scan.onmarked = onmarked;
scan.start();
}
mui.plusReady(function() {
function onmarked(type, result) {
var text = '未知: ';
switch(type) {
case plus.barcode.QR:
text = 'QR: ';
break;
case plus.barcode.EAN13:
text = 'EAN13: ';
break;
case plus.barcode.EAN8:
text = 'EAN8: ';
break;
case plus.barcode.CODE39:
text = 'CODE39: ';
break;
case plus.barcode.CODE93:
text = 'CODE93: ';
break;
case plus.barcode.CODE128:
text = 'CODE128: ';
break;
}
console.log(text + result);
if(result) {
console.log(result)
// scan.close();
// window.location.reload();
scan.cancel();
setTimeout(() => {
scan.start();
},1000)
}
}
mui("body").on('tap', '#scan-go', function() {
mui.openWindow({
url: 'scan_success.html',
id: 'scan_success.html',
styles: { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置
titleNView: { // 窗口的标题栏控件
autoBackButton: true,
titleText: '出仓成功', // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor: "#000000", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize: "17px", // 字体大小,默认17px
backgroundColor: "#FFCC00", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
}
}
});
})
})
</script>
</body>
</html>
收起阅读 »
5+App升级iOS12系统后应用可能崩溃的解决方案
部分开发者反馈app在iOS12上会崩溃,而同样代码在iOS12以下的手机正常。但也并非所有代码写法都会引发崩溃。
苹果最新的策略在iOS12及以后系统将不再维护UIWebview内核,都推荐改为WKWebview。
目前5+App、wap2app打包时,默认是UIWebview。uni-app默认是WKWebview。
所以5+App、wap2app的开发者,如果遇到iOS12的兼容问题,有如下方案:
1. 将app的iOS webview内核更改为WKWebview
在manifest.json的plus->kernel->ios节点中配置默认使用WKWebviwe内核:
//...
"plus": {
"kernel": {
"ios": "WKWebview"
},
//...
}
注意:
- 目前使用WKWebview内核不支持“启用js原生混淆”功能,云端打包iOS时不要勾选此项配置。
- wgt资源加密要注意,iOS一旦使用WKWebview也不支持解压加密的wgt资源。
- WKWebview里HTML5的存储如cookie、localstorage等和UIWebview不互通,应用升级后,手机端老的cookie等数据拿不到了。
- WKWebview不支持overrideresource。
2. 优化代码写法,避免崩溃
如果代码里有容易引发内存占用且没有回收的代码,比如不停运行的计时器,在UIWebview下更容易崩溃。
在js里不停大范围修改整体dom引发不停重布局,也容易崩溃。
如果配置为WKWebviw内核还存在闪退问题,请提供出现问题的ipa,并详细说明操作出现闪退的步骤。
另,由于一个三方库和iOS12的模拟器冲突了,HBuilde早期版本在真机运行到iOS12模拟器会无法启动,请升级到最新版。此问题不影响真机。
部分开发者反馈app在iOS12上会崩溃,而同样代码在iOS12以下的手机正常。但也并非所有代码写法都会引发崩溃。
苹果最新的策略在iOS12及以后系统将不再维护UIWebview内核,都推荐改为WKWebview。
目前5+App、wap2app打包时,默认是UIWebview。uni-app默认是WKWebview。
所以5+App、wap2app的开发者,如果遇到iOS12的兼容问题,有如下方案:
1. 将app的iOS webview内核更改为WKWebview
在manifest.json的plus->kernel->ios节点中配置默认使用WKWebviwe内核:
//...
"plus": {
"kernel": {
"ios": "WKWebview"
},
//...
}
注意:
- 目前使用WKWebview内核不支持“启用js原生混淆”功能,云端打包iOS时不要勾选此项配置。
- wgt资源加密要注意,iOS一旦使用WKWebview也不支持解压加密的wgt资源。
- WKWebview里HTML5的存储如cookie、localstorage等和UIWebview不互通,应用升级后,手机端老的cookie等数据拿不到了。
- WKWebview不支持overrideresource。
2. 优化代码写法,避免崩溃
如果代码里有容易引发内存占用且没有回收的代码,比如不停运行的计时器,在UIWebview下更容易崩溃。
在js里不停大范围修改整体dom引发不停重布局,也容易崩溃。
如果配置为WKWebviw内核还存在闪退问题,请提供出现问题的ipa,并详细说明操作出现闪退的步骤。
另,由于一个三方库和iOS12的模拟器冲突了,HBuilde早期版本在真机运行到iOS12模拟器会无法启动,请升级到最新版。此问题不影响真机。
收起阅读 »
uni-app 中清除定时器
无论是获取短信码,还是在活动页轮询获取当前活动最新信息,都需要用到定时器。
但是,定时器如果不及时合理地清除,会造成业务逻辑混乱甚至应用卡死的情况。
uni-app 中在某个页面中启动定时器后,一定要在页面关闭时将定时器清除掉。即在页面卸载(关闭)的生命周期函数里,清除定时器。
onUnload:function(){
if(this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
附件中提供了简单的 demo,下载后直接在 HBuilderX 中运行即可。
无论是获取短信码,还是在活动页轮询获取当前活动最新信息,都需要用到定时器。
但是,定时器如果不及时合理地清除,会造成业务逻辑混乱甚至应用卡死的情况。
uni-app 中在某个页面中启动定时器后,一定要在页面关闭时将定时器清除掉。即在页面卸载(关闭)的生命周期函数里,清除定时器。
onUnload:function(){
if(this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
附件中提供了简单的 demo,下载后直接在 HBuilderX 中运行即可。
收起阅读 »
android开发之仿商城首页Banner图的实现
实现效果:当banner滚动的时候 首先会缩放当前以及上一个或下一个banner图,当banner滚动时会,背景会随滚动系数变化缩放(自动滚动),下面相关技术人员来分享一下源码:
//0无状态,1缩放,2放大,3不能再播放动画
private int status = 0;
private void fada() {
if (status == 0 || status == 1) {
AnimatorSet animatorSetsuofang = new AnimatorSet();//组合动画
ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewPager, "scaleX", 0.9f, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(viewPager, "scaleY", 0.9f, 1f);
animatorSetsuofang.setDuration(500);
animatorSetsuofang.setInterpolator(new LinearInterpolator());
animatorSetsuofang.play(scaleX).with(scaleY);//两个动画同时开始
animatorSetsuofang.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
setViewPagerIsScroll(false);
stopAutoPlay();
status = 3;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setViewPagerIsScroll(true);
Log.e("as", "sa");
startAutoPlay();
status = 2;
}
});
animatorSetsuofang.start();
}
}
private void suoxia() {
if (status == 0 || status == 2) {
AnimatorSet animatorSetsuofang = new AnimatorSet();//组合动画
ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewPager, "scaleX", 1f, 0.9f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(viewPager, "scaleY", 1f, 0.9f);
animatorSetsuofang.setDuration(200);
animatorSetsuofang.setInterpolator(new LinearInterpolator());
animatorSetsuofang.play(scaleX).with(scaleY);//两个动画同时开始
animatorSetsuofang.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
setViewPagerIsScroll(false);
stopAutoPlay();
status = 3;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setViewPagerIsScroll(true);
// startAutoPlay();
status = 1;
}
});
animatorSetsuofang.start();
}
}
动画联动效果实现:
private final Runnable task = new Runnable() {
@Override
public void run() {
if (status == 0 || status == 2) {
AnimatorSet animatorSetsuofang = new AnimatorSet();//组合动画
ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewPager, "scaleX", 1f, 0.9f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(viewPager, "scaleY", 1f, 0.9f);
animatorSetsuofang.setDuration(300);
animatorSetsuofang.setInterpolator(new LinearInterpolator());
animatorSetsuofang.play(scaleX).with(scaleY);//两个动画同时开始
animatorSetsuofang.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
setViewPagerIsScroll(false);
status = 3;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setViewPagerIsScroll(true);
if (count > 1 && isAutoPlay) {
currentItem = currentItem % (count + 1) + 1;
// Log.i(tag, "curr:" + currentItem + " count:" + count);
if (currentItem == 1) {
viewPager.setCurrentItem(currentItem, false);
handler.post(task);
} else {
viewPager.setCurrentItem(currentItem);
handler.postDelayed(task, delayTime);
}
}
status = 1;
}
});
animatorSetsuofang.start();
}
}
};
缩放(拖动)效果实现:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int num = 0;
if (mOnPageChangeListener != null) {
// Log.e("as", "position" + position + " ----positionOffset " + positionOffset + " positionOffsetPixels" + positionOffsetPixels);
// Log.e(scale);
Log.e("as", imageUrls.size() + "" + " currentItem" + currentItem);
if (positionOffset > 0) {
Log.e("as", "position" + position + " currentItem" + currentItem + "mViewPagerIndex" + mViewPagerIndex);
// Log.e("as", mViewPagerIndex + "");
if (touch) {
if (currentItem == imageUrls.size() + 1) {
Glide.with(context).load(imageUrls.get(0)).into(roundImageView);
Glide.with(context).load(imageUrls.get(0)).into(roundImagetwo);
} else {
if (currentItem == 0) {
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImagetwo);
} else {
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImagetwo);
}
}
if (position == mViewPagerIndex) {
Log.e("tt", "左");
if (position == imageUrls.size()) {
num = 0;
} else {
num = position;
}
Glide.with(context).load(imageUrls.get(num)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
roundImageView.setVisibility(VISIBLE);
roundImagetwo.setVisibility(INVISIBLE);
} else {
Log.e("tt", "右");
if (position == 0) {
num = imageUrls.size();
} else {
num = position;
}
Glide.with(context).load(imageUrls.get(num - 1)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
roundImagetwo.setVisibility(VISIBLE);
roundImageView.setVisibility(INVISIBLE);
}
} else {
if (!touchover) {
if (position < currentItem) {
roundImageView.setVisibility(VISIBLE);
roundImagetwo.setVisibility(INVISIBLE);
}
}
if (position == imageUrls.size()) {
Glide.with(context).load(imageUrls.get(0)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else if (position == 0) {
num = imageUrls.size();
Glide.with(context).load(imageUrls.get(num - 1)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else {
if (position == mViewPagerIndex) {
Glide.with(context).load(imageUrls.get(position)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else {
if (!touchover) {
Glide.with(context).load(imageUrls.get(position)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else {
Glide.with(context).load(imageUrls.get(position - 1)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
roundImageView.setVisibility(INVISIBLE);
roundImagetwo.setVisibility(VISIBLE);
}
//
}
}
}
//
} else {
roundImagetwo.setVisibility(VISIBLE);
roundImageView.setVisibility(VISIBLE);
if (currentItem == imageUrls.size() + 1) {
Glide.with(context).load(imageUrls.get(0)).into(roundImageView);
Glide.with(context).load(imageUrls.get(0)).into(roundImagetwo);
} else {
if (currentItem == 0) {
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImagetwo);
} else {
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImagetwo);
}
}
}
roundImagetwo.setRound(1f - positionOffset);
roundImageView.setRound(positionOffset);
if ((positionOffset == 0) && touch == false) {
fada();
}
mOnPageChangeListener.onPageScrolled(toRealPosition(position), positionOffset, positionOffsetPixels);
}
}
轮播图数据绑定
banner.setImages(imagebgUrls)
.setImageLoader(new GlideImageLoader())
.setImageList(images)
.start();
好了,到这里就算是完后才能了,如果大家需要改banner依赖包的setImageList()方法,不然无法在主线程中添加数据,还存在不理解的地方也是可以留言咨询。
本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处!
实现效果:当banner滚动的时候 首先会缩放当前以及上一个或下一个banner图,当banner滚动时会,背景会随滚动系数变化缩放(自动滚动),下面相关技术人员来分享一下源码:
//0无状态,1缩放,2放大,3不能再播放动画
private int status = 0;
private void fada() {
if (status == 0 || status == 1) {
AnimatorSet animatorSetsuofang = new AnimatorSet();//组合动画
ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewPager, "scaleX", 0.9f, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(viewPager, "scaleY", 0.9f, 1f);
animatorSetsuofang.setDuration(500);
animatorSetsuofang.setInterpolator(new LinearInterpolator());
animatorSetsuofang.play(scaleX).with(scaleY);//两个动画同时开始
animatorSetsuofang.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
setViewPagerIsScroll(false);
stopAutoPlay();
status = 3;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setViewPagerIsScroll(true);
Log.e("as", "sa");
startAutoPlay();
status = 2;
}
});
animatorSetsuofang.start();
}
}
private void suoxia() {
if (status == 0 || status == 2) {
AnimatorSet animatorSetsuofang = new AnimatorSet();//组合动画
ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewPager, "scaleX", 1f, 0.9f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(viewPager, "scaleY", 1f, 0.9f);
animatorSetsuofang.setDuration(200);
animatorSetsuofang.setInterpolator(new LinearInterpolator());
animatorSetsuofang.play(scaleX).with(scaleY);//两个动画同时开始
animatorSetsuofang.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
setViewPagerIsScroll(false);
stopAutoPlay();
status = 3;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setViewPagerIsScroll(true);
// startAutoPlay();
status = 1;
}
});
animatorSetsuofang.start();
}
}
动画联动效果实现:
private final Runnable task = new Runnable() {
@Override
public void run() {
if (status == 0 || status == 2) {
AnimatorSet animatorSetsuofang = new AnimatorSet();//组合动画
ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewPager, "scaleX", 1f, 0.9f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(viewPager, "scaleY", 1f, 0.9f);
animatorSetsuofang.setDuration(300);
animatorSetsuofang.setInterpolator(new LinearInterpolator());
animatorSetsuofang.play(scaleX).with(scaleY);//两个动画同时开始
animatorSetsuofang.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
setViewPagerIsScroll(false);
status = 3;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setViewPagerIsScroll(true);
if (count > 1 && isAutoPlay) {
currentItem = currentItem % (count + 1) + 1;
// Log.i(tag, "curr:" + currentItem + " count:" + count);
if (currentItem == 1) {
viewPager.setCurrentItem(currentItem, false);
handler.post(task);
} else {
viewPager.setCurrentItem(currentItem);
handler.postDelayed(task, delayTime);
}
}
status = 1;
}
});
animatorSetsuofang.start();
}
}
};
缩放(拖动)效果实现:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int num = 0;
if (mOnPageChangeListener != null) {
// Log.e("as", "position" + position + " ----positionOffset " + positionOffset + " positionOffsetPixels" + positionOffsetPixels);
// Log.e(scale);
Log.e("as", imageUrls.size() + "" + " currentItem" + currentItem);
if (positionOffset > 0) {
Log.e("as", "position" + position + " currentItem" + currentItem + "mViewPagerIndex" + mViewPagerIndex);
// Log.e("as", mViewPagerIndex + "");
if (touch) {
if (currentItem == imageUrls.size() + 1) {
Glide.with(context).load(imageUrls.get(0)).into(roundImageView);
Glide.with(context).load(imageUrls.get(0)).into(roundImagetwo);
} else {
if (currentItem == 0) {
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImagetwo);
} else {
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImagetwo);
}
}
if (position == mViewPagerIndex) {
Log.e("tt", "左");
if (position == imageUrls.size()) {
num = 0;
} else {
num = position;
}
Glide.with(context).load(imageUrls.get(num)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
roundImageView.setVisibility(VISIBLE);
roundImagetwo.setVisibility(INVISIBLE);
} else {
Log.e("tt", "右");
if (position == 0) {
num = imageUrls.size();
} else {
num = position;
}
Glide.with(context).load(imageUrls.get(num - 1)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
roundImagetwo.setVisibility(VISIBLE);
roundImageView.setVisibility(INVISIBLE);
}
} else {
if (!touchover) {
if (position < currentItem) {
roundImageView.setVisibility(VISIBLE);
roundImagetwo.setVisibility(INVISIBLE);
}
}
if (position == imageUrls.size()) {
Glide.with(context).load(imageUrls.get(0)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else if (position == 0) {
num = imageUrls.size();
Glide.with(context).load(imageUrls.get(num - 1)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else {
if (position == mViewPagerIndex) {
Glide.with(context).load(imageUrls.get(position)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else {
if (!touchover) {
Glide.with(context).load(imageUrls.get(position)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
} else {
Glide.with(context).load(imageUrls.get(position - 1)).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImagebg);
roundImageView.setVisibility(INVISIBLE);
roundImagetwo.setVisibility(VISIBLE);
}
//
}
}
}
//
} else {
roundImagetwo.setVisibility(VISIBLE);
roundImageView.setVisibility(VISIBLE);
if (currentItem == imageUrls.size() + 1) {
Glide.with(context).load(imageUrls.get(0)).into(roundImageView);
Glide.with(context).load(imageUrls.get(0)).into(roundImagetwo);
} else {
if (currentItem == 0) {
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(imageUrls.size() - 1)).into(roundImagetwo);
} else {
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImageView);
Glide.with(context).load(imageUrls.get(currentItem - 1)).into(roundImagetwo);
}
}
}
roundImagetwo.setRound(1f - positionOffset);
roundImageView.setRound(positionOffset);
if ((positionOffset == 0) && touch == false) {
fada();
}
mOnPageChangeListener.onPageScrolled(toRealPosition(position), positionOffset, positionOffsetPixels);
}
}
轮播图数据绑定
banner.setImages(imagebgUrls)
.setImageLoader(new GlideImageLoader())
.setImageList(images)
.start();
好了,到这里就算是完后才能了,如果大家需要改banner依赖包的setImageList()方法,不然无法在主线程中添加数据,还存在不理解的地方也是可以留言咨询。
本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处!

使用uni.navigateBack修改上一个页面值,多页面传参通信解决方案
此类需求大概意思是:A页面进入B页面,B页面返回并传值给A。
var pages = getCurrentPages();
var currPage = pages[pages.length - 1]; //当前页面
var prevPage = pages[pages.length - 2]; //上一个页面
//直接调用上一个页面的setData()方法,把数据存到上一个页面中去
prevPage.setData({
mdata:1
})
uni.navigateBack(); //上一个页面数据无法修改
解决方案:onfire.js 是一个很简单的事件分发的Javascript库(仅仅 0.9kb),简洁实用。github地址:https://github.com/hustcc/onfire.js/blob/master/README_zh.md
可以用于:
- 简单的事件分发;
- 在 react / vue.js / angular 用于跨组件的轻量级实现;
- 事件订阅和发布;
A页面:
onShow:function(){
var that = this;
onfire.on('setAddressInfo',function(addressInfo){
that.addressInfo = addressInfo;
})
},
B页面:
selectText: function(e){
var that = this;
var that_addressInfo ={
location: e.currentTarget.id
}
onfire.fire('setAddressInfo',that_addressInfo);
uni.navigateBack();
}
参考来源:https://juejin.im/post/5907f120b123db3ee48d2a4f
此类需求大概意思是:A页面进入B页面,B页面返回并传值给A。
var pages = getCurrentPages();
var currPage = pages[pages.length - 1]; //当前页面
var prevPage = pages[pages.length - 2]; //上一个页面
//直接调用上一个页面的setData()方法,把数据存到上一个页面中去
prevPage.setData({
mdata:1
})
uni.navigateBack(); //上一个页面数据无法修改
解决方案:onfire.js 是一个很简单的事件分发的Javascript库(仅仅 0.9kb),简洁实用。github地址:https://github.com/hustcc/onfire.js/blob/master/README_zh.md
可以用于:
- 简单的事件分发;
- 在 react / vue.js / angular 用于跨组件的轻量级实现;
- 事件订阅和发布;
A页面:
onShow:function(){
var that = this;
onfire.on('setAddressInfo',function(addressInfo){
that.addressInfo = addressInfo;
})
},
B页面:
selectText: function(e){
var that = this;
var that_addressInfo ={
location: e.currentTarget.id
}
onfire.fire('setAddressInfo',that_addressInfo);
uni.navigateBack();
}
参考来源:https://juejin.im/post/5907f120b123db3ee48d2a4f
收起阅读 »