package com.excel.test;
import java.util.StringTokenizer;
public class StringTok {
public static void main(String[] args) {
/**
* 第一个字符串为要拆分对象,第二个字符串为拆分方式,支持正则
*/
StringTokenizer st = new StringTokenizer("zhang;quan;zhong", "[;|;]");
/**
* 以下这两个使用方式一致
* while(st.hasMoreTokens()) {
String s = st.nextToken();
System.out.println(s);
System.out.println("-----------");
}
*/
while(st.hasMoreElements()) {
Object o = st.nextElement();
System.out.println(o);
System.out.println("=============");
}
}
}
CCTextFieldTTF是cocos2d-x封装的输入框控件,主要配合CCTextFieldDelegate和CCTouchDelegate两个代理接口使用,前者是用来处理文字的输入删除操作的代理类,后者是用来触发打开和关闭输入法键盘的。
借鉴网友oneRain88的“带光标的输入框”文章,在其基础上加入了密码框星号显示设置,字符长度设置,触摸弹出输入法区域设置。
文章链接:http://blog.csdn.net/onerain88/article/details/7572315,这篇文章对CCTextFieldTTF的使用原理讲的很好,封装的思路也很好,想了解原理可以去读读,本人只是在他的基础上加了一些小功能。在此也谢谢oneRain88的分享。
#ifndef DTCursorTextField_h
#define DTCursorTextField_h
#include "cocos2d.h"
USING_NS_CC;
class DTCursorTextField: public CCTextFieldTTF, public CCTouchDelegate
,public CCTextFieldDelegate
{
private:
// 点击开始位置
CCPoint m_beginPos;
// 光标精灵
CCSprite *m_pCursorSprite;
// 光标动画
CCAction *m_pCursorAction;
// 光标坐标
CCPoint m_cursorPos;
// 是否加密显示
bool isPsw;
int m_limitNum;
// 输入框内容
//std::string *m_pInputText;
CCSize m_designedSize;
public:
DTCursorTextField();
~DTCursorTextField();
// static,暂时不能使用
// static DTCursorTextField * textFieldWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize);
/** creates a CCLabelTTF from a fontname and font size */
static DTCursorTextField * textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);
// CCLayer
void onEnter();
void onExit();
// 初始化光标精灵
void initCursorSprite(int nHeight);
void setColor(const ccColor3B& color3);
// CCTextFieldDelegate
virtual bool onTextFieldAttachWithIME(CCTextFieldTTF *pSender);
virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender);
virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);
virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen);
// CCLayer Touch
bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
// 判断是否点击在TextField处
bool isInTextField(CCTouch *pTouch);
// 得到TextField矩形
CCRect getRect();
// 打开输入法
void openIME();
// 关闭输入法
void closeIME();
//设置是否星号显示
bool getIsPsw();
void setIsPsw(bool bFlag);
//设置字符长度限制,一个汉字三个字符
void setLimitNum(int limitNum);
int getLimitNum();
//重载原函数,用来显示星号
void setString(const char* displayTx, const char* inputTx);
//点击弹出输入法的尺寸范围
void setDesignedSize(CCSize size);
CCSize getDesignedSize();
};
#endif
#include "DTCursorTextField.h"
#include "CCNotificationCenter.h"
static int _calcCharCount(const char * pszText)
{
int n = 0;
char ch = 0;
while ((ch = *pszText))
{
CC_BREAK_IF(! ch);
if (0x80 != (0xC0 & ch))
{
++n;
}
++pszText;
}
return n;
}
const static float DELTA = 20.0f;
DTCursorTextField::DTCursorTextField()
{
CCTextFieldTTF();
m_pCursorSprite = NULL;
m_pCursorAction = NULL;
m_pInputText = NULL;
isPsw = false;
m_limitNum = 30;
}
DTCursorTextField::~DTCursorTextField()
{
//delete m_pInputText;
}
void DTCursorTextField::onEnter()
{
CCTextFieldTTF::onEnter();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, false);
this->setDelegate(this);
}
//静态生成函数
DTCursorTextField * DTCursorTextField::textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize)
{
DTCursorTextField *pRet = new DTCursorTextField();
if(pRet && pRet->initWithString("", fontName, fontSize))
{
pRet->autorelease();
if (placeholder)
{
pRet->setPlaceHolder(placeholder);
}
pRet->initCursorSprite(fontSize);
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
void DTCursorTextField::initCursorSprite(int nHeight)
{
// 初始化光标
int column = 4;
int pixels[nHeight][column];
for (int i=0; i<nHeight; ++i) {
for (int j=0; j<column; ++j) {
pixels[i][j] = 0xffffffff;
}
}
CCTexture2D *texture = new CCTexture2D();
texture->initWithData(pixels, kCCTexture2DPixelFormat_RGB888, 1, 1, CCSizeMake(column, nHeight));
m_pCursorSprite = CCSprite::create(texture);
CCSize winSize = getContentSize();
m_cursorPos = ccp(0, winSize.height / 2);
m_pCursorSprite->setPosition(m_cursorPos);
this->addChild(m_pCursorSprite);
m_pCursorAction = CCRepeatForever::create((CCActionInterval *) CCSequence::create(CCFadeOut::create(0.25f), CCFadeIn::create(0.25f), NULL));
m_pCursorSprite->runAction(m_pCursorAction);
m_pInputText = new std::string();
}
bool DTCursorTextField::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
m_beginPos = pTouch->locationInView();
m_beginPos = CCDirector::sharedDirector()->convertToGL(m_beginPos);
return true;
}
CCRect DTCursorTextField::getRect()
{
CCSize size;
if (&m_designedSize != NULL) {
size = m_designedSize;
}else {
size = getContentSize();
}
CCRect rect = CCRectMake(0 - size.width * getAnchorPoint().x, 0 - size.height * getAnchorPoint().y, size.width, size.height);
return rect;
}
//设置触摸弹出输入法的区域大小
void DTCursorTextField::setDesignedSize(cocos2d::CCSize size)
{
m_designedSize = size;
}
CCSize DTCursorTextField::getDesignedSize()
{
return m_designedSize;
}
bool DTCursorTextField::isInTextField(cocos2d::CCTouch *pTouch)
{
CCPoint pToushPos = convertTouchToNodeSpaceAR(pTouch);
return CCRect::CCRectContainsPoint(getRect(), pToushPos);
}
void DTCursorTextField::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
CCPoint endPos = pTouch->locationInView();
endPos = CCDirector::sharedDirector()->convertToGL(endPos);
// 判断是否为点击事件
if (::abs(endPos.x - m_beginPos.x) > DELTA ||
::abs(endPos.y - m_beginPos.y) > DELTA)
{
// 不是点击事件
m_beginPos.x = m_beginPos.y = -1;
return;
}
CCLOG("width: %f, height: %f.", getContentSize().width, getContentSize().height);
// 判断是打开输入法还是关闭输入法
isInTextField(pTouch) ? openIME() : closeIME();
}
bool DTCursorTextField::onTextFieldAttachWithIME(cocos2d::CCTextFieldTTF *pSender)
{
if (m_pInputText->empty()) {
return false;
}
m_pCursorSprite->setPositionX(getContentSize().width);
return false;
}
bool DTCursorTextField::onTextFieldInsertText(cocos2d::CCTextFieldTTF *pSender, const char *text, int nLen)
{
CCLOG("Width: %f", pSender->getContentSize().width);
CCLOG("Text: %s", text);
CCLOG("Length: %d", nLen);
std::string tempStr = m_pInputText->substr();
tempStr.append(text);
if (tempStr.length() > m_limitNum) {
return true;
}
m_pInputText->append(text);
if (isPsw) {
std::string tempStr;
for (int i = 0; i < m_pInputText->size(); i++) {
tempStr.append("*");
}
setString(tempStr.c_str(), m_pInputText->c_str());
}else {
setString(m_pInputText->c_str(), m_pInputText->c_str());
}
m_pCursorSprite->setPositionX(getContentSize().width);
return true;
}
bool DTCursorTextField::onTextFieldDeleteBackward(cocos2d::CCTextFieldTTF *pSender, const char *delText, int nLen)
{
m_pInputText->resize(m_pInputText->size() - nLen);
CCLog(m_pInputText->c_str());
if (isPsw) {
std::string tempStr;
for (int i = 0; i < m_pInputText->size(); i++) {
tempStr.append("*");
}
setString(tempStr.c_str(), m_pInputText->c_str());
}else {
setString(m_pInputText->c_str(), m_pInputText->c_str());
}
m_pCursorSprite->setPositionX(getContentSize().width);
if (m_pInputText->empty()) {
m_pCursorSprite->setPositionX(0);
}
return true;
}
bool DTCursorTextField::onTextFieldDetachWithIME(cocos2d::CCTextFieldTTF *pSender)
{
return false;
}
void DTCursorTextField::openIME()
{
m_pCursorSprite->setVisible(true);
this->attachWithIME();
}
void DTCursorTextField::closeIME()
{
m_pCursorSprite->setVisible(false);
this->detachWithIME();
}
void DTCursorTextField::onExit()
{
this->detachWithIME();
CCTextFieldTTF::onExit();
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
bool DTCursorTextField::getIsPsw()
{
return isPsw;
}
//设置星号显示否
void DTCursorTextField::setIsPsw( bool bFlag)
{
isPsw = bFlag;
}
int DTCursorTextField::getLimitNum()
{
return m_limitNum;
}
//设置字符长度
void DTCursorTextField::setLimitNum(int limitNum)
{
m_limitNum = limitNum;
}
void DTCursorTextField::setString(const char *displayTx, const char* inputTx)
{
CC_SAFE_DELETE(m_pInputText);
if (inputTx)
{
m_pInputText = new std::string(inputTx);
}
else
{
m_pInputText = new std::string;
}
// if there is no input text, display placeholder instead
if (! m_pInputText->length())
{
CCLabelTTF::setString(m_pPlaceHolder->c_str());
}
else
{
CCLabelTTF::setString(displayTx);
}
m_nCharCount = _calcCharCount(m_pInputText->c_str());
}
void DTCursorTextField::setColor(const ccColor3B& color3)
{
m_sColor = m_sColorUnmodified = color3;
if (m_bOpacityModifyRGB)
{
m_sColor.r = color3.r * m_nOpacity/255.0f;
m_sColor.g = color3.g * m_nOpacity/255.0f;
m_sColor.b = color3.b * m_nOpacity/255.0f;
}
updateColor();
m_pCursorSprite->setColor(color3);
}
使用的时候,直接使用textFieldWithPlaceHolder函数生成一个对象指针,setIsPsw,setLimitNum,setDesignedSize,setColor分别实现星号显示,字符长度,触摸弹出输入法区域大小,字符颜色。
注释比较简单,欢迎指正讨论。
转自:http://www.cnblogs.com/jz1108/archive/2011/09/23/2185444.html
本文将向大家介绍如何使用百度地图API提供的驾车导航服务进行开发。
一个简单的示例
驾车导航服务根据传入的起点和终点信息给出从起点到终点的驾车路线,我们先从一个最简单的示例看起:
var map = new BMap.Map('container');
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
var driving = new BMap.DrivingRoute(map, {
renderOptions: {
map: map
}
});
driving.search('圆明园', '西单');
上面代码很简单,先初始化地图(地图容器的html代码省略),接着实例化一个DrivingRoute类,并配置好参数(参数具体含义后续再说)。最后调用该实例的search方法进行驾车方案查询。我们会在浏览器看到如下效果:
DrivingRoute的构造函数的第一个参数制定检索的范围,这里我们传递的是map实例,也就是说驾车导航的位置会根据当前地图中心点所在的城市进行检索。当然你也可以传递一个城市名称的字符串:
var driving = new BMap.DrivingRoute("北京", {
renderOptions: {
map: map
}
});
DrivingRoute的构造函数第二个参数是可选的配置,类型为DrivingRouteOptions。这里我们只使用了renderOptions属性,这个属性值的类型为DrivingRenderOptions类,它是用来控制检索结果的呈现的,比如是否将结果线路呈现在地图上,是否将详细方案描述呈现在页面的某个位置等等。这里我们使用了map属性,即让检索结果自动展现在地图上,这样我们就会看到地图上有起点、终点以及它们之间的线路了。
其他发起检索的方式
除了使用字符串方式发起驾车检索以外,还可以使用坐标发起:
driving.search(new BMap.Point(116.404, 39.915), new BMap.Point(116.389, 39.811));
使用坐标发起检索时,起点和终点没有具体的描述,仅仅用“起点”和“终点”进行描述。
通过文档看,search还支持LocalResultPoi类型,该类型没有构造函数,但是可以通过字面量形式表示。我们可以自己构造这个类型的实例并发起驾车检索:
driving.search({title: '我的家', point: new BMap.Point(116.410, 39.915)}, {title: '你的家', point: new BMap.Point(116.400, 39.910)});
这样,API就会用开发者自定义的名称进行显示。当然通过LocalSearch获取的结果类型也是LocalResultPoi,也可以直接将结果对象传递到search方法中。
呈现设置
除了设置展现的地图以外,呈现设置中还有很多其他功能,最常用的就是将详细方案描述显示在页面上:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>驾车导航</title>
<script src="http://api.map.baidu.com/api?v=1.2"></script>
</head>
<body>
<div id="container" ></div>
<div id="panel" ></div>
<script>var map =new BMap.Map('container');
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
var driving =new BMap.DrivingRoute(map, {
renderOptions: {
map: map,
panel: 'panel'
}
});
driving.search('圆明园', '西单');
</script>
</body>
</html>
这里我们增加一个div,id为panel,接着在renderOptions中增加panel属性,把div的id传递进去。我们会看到如下效果:
API会将详细的驾车方案描述填充到id为panel的div容器中。此时点击panel中的具体方案会在图区产生交互效果。
另外,呈现设置的enableDragging如果设置为true的画,则用户可以在地图上拖拽起点、终点改变驾车方案,也可以任意拖拽修改途径点:
var driving = new BMap.DrivingRoute(map, {
renderOptions: {
map: map,
panel: 'panel',
enableDragging: true
}
});
highlightMode属性可以控制点击panel中的方案描述时展示点位置还是展示一段路线,它支持如下两个值:
- BMAP_HIGHLIGHT_STEP:展现关键点
- BMAP_HIGHLIGHT_ROUTE:展现路段
默认为展现关键点,如下图:
点击描述的第三项,显示一个关键点信息(根据描述,这个点就是在中关村一桥左转的位置点),也可以显示路线:
这时,再选中第三步的时候,地图展现的是一段线路(即“沿中关村北大街行驶1.6公里”这段路)。
驾车策略配置
在DrivingRouteOptions还有一个控制策略的属性drivingPolicy,它的属性值可以为以下几种:
- BMAP_DRIVING_POLICY_LEAST_TIME:最少时间,默认
- BMAP_DRIVING_POLICY_LEAST_DISTANCE:最短距离
- BMAP_DRIVING_POLICY_AVOID_HIGHWAYS:避开高速
通过配置策略可获得不同的驾车方案。
回调函数
在DrivingRouteOptions里面还有很多回调函数属性,比如:onSearchComplete、onMarkersSet、onInfoHtmlSet、onPolylinesSet和onResultsHtmlSet。在DrivingRoute类上也有对应的设置回调的方法:setSearchCompleteCallback、setMarkersSetCallback等等。实际上不论通过配置参数传递还是通过接口设置回调,其作用都是一样的。这些回调到底有什么用处呢?
通过回调函数,开发者可获得更多的数据资源,可以利用这些数据资源更好、更灵活的进行二次开发。下面这个示例就是利用onSearchComplete获取数据自行添加覆盖物和描述信息:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>驾车导航</title>
<script src="http://api.map.baidu.com/api?v=1.2"></script>
</head>
<body>
<div id="container" ></div>
<div id="panel" ></div>
<script>var map =new BMap.Map('container');
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
var driving =new BMap.DrivingRoute(map, {
onSearchComplete: function(results){
if (driving.getStatus() == BMAP_STATUS_SUCCESS) {
// 地图覆盖物 addOverlays(results);
// 方案描述 addText(results);
}
}
});
driving.search('圆明园', '西单');
// 添加覆盖物并设置视野function addOverlays(results) {
// 自行添加起点和终点var start = results.getStart();
var end = results.getEnd();
addStart(start.point, start.title);
addEnd(end.point, end.title);
var viewPoints = [start.point, end.point];
// 获取方案var plan = results.getPlan(0);
// 获取方案中包含的路线for (var i =0; i < plan.getNumRoutes(); i ++) {
addRoute(plan.getRoute(i).getPath());
viewPoints.concat(plan.getRoute(i).getPath());
}
// 设置地图视野 map.setViewport(viewPoints, {
margins: [40, 10, 10, 10]
});
}
// 添加方案描述function addText(results) {
var plan = results.getPlan(0);
// 获取方案中包含的路线var htmls = [];
for (var i =0; i < plan.getNumRoutes(); i ++) {
var route = plan.getRoute(i);
for (var j =0; j < route.getNumSteps(); j ++) {
var curStep = route.getStep(j);
htmls.push((j +1) +'. '+ curStep.getDescription() +'<br />');
}
}
var panel = document.getElementById('panel');
panel.innerHTML = htmls.join('');
panel.style.lineHeight ='1.4em';
panel.style.fontSize ='12px';
}
// 添加起点覆盖物function addStart(point, title){
map.addOverlay(new BMap.Marker(point, {
title: title,
icon: new BMap.Icon('blue.png', new BMap.Size(38, 41), {
anchor: new BMap.Size(4, 36)
})}));
}
// 添加终点覆盖物function addEnd(point, title){
map.addOverlay(new BMap.Marker(point, {
title: title,
icon: new BMap.Icon('red.png', new BMap.Size(38, 41), {
anchor: new BMap.Size(4, 36)
})}));
}
// 添加路线function addRoute(path){
map.addOverlay(new BMap.Polyline(path, {
strokeColor: '#333',
enableClicking: false
}));
}
</script>
</body>
</html>
在上面的代码中,我们初始化DrivingRoute实例时没有设置renderOptions,也就是说驾车导航的结果不会自动添加到地图上,描述信息也不会展现在页面中,我们通过onSearchComplete获取数据自行添加。onSearchComplete回调函数的参数为一个DrivingRouteResult对象,通过它可以获取数据信息。在回调函数中我们首先判断一下检索是否成功,如果成功则添加覆盖物和描述信息。在添加覆盖物完成后,我们调用了Map的setViewport方法来设置视野,以便让结果完整展示在地图当中。在获取方案的时候我们调用getPlan方法并给定索引0,这表示获取第一条驾车方案(实际上目前仅有一条驾车方案,但是以后可能会同时给出多条方案)。每个方案通过RoutePlan描述,方案中会包含若干Route对象,它表示两点间的线路(在只有一个目的地的情况下,Route对象数量总为1),Route对象又包含若干Step,通过getStep方法可获得,Step对象描述了每一个关键点的信息。
以上代码在浏览器中的效果如下:
通过接口,你还可以进一步丰富这个功能,比如增加一些点击交互。
需要注意的问题
搜索没有结果
如果检索关键字过于模糊,比如从“麦当劳”到“肯德基”,这样API不知道从哪个麦当劳到哪个肯德基,所以此时将无法获取导航线路。为了让导航返回更准确的结果,建议使用Point类型或LocalSearchPoi类型发起检索。
发起新检索后地图没有清除上一次结果
在一般情况下,你只需要一个DrivingRoute实例做检索,同一个实例在检索的时候会自动清除上一次检索的结果(包括地图覆盖物和描述)。但是如果每次检索都new一个新的DrivingRoute实例,那么每个实例的检索结果都会出现在地图上,无法自动清除。