写一下前些日子云app开发的遇到的一些细节问题。
1、scrollview的问题
首先是关于scrollview这个类的。观察了已经上线的一些云应用,对于scrollview都好像没有处理的太好。这个view是绑定在容器上的一个滑动组件,但云app不像android在对组件的调用时只需要代码写好就可以了,云app更多的还需要DOM的格式问题。在这个问题上很多应用都会出现类似与滑动条跑到header上去了这种事情。
<?xml version="1.0" encoding="utf-8"?> <div id="home"> <div > <a _action="/blog_article/go_back/index.html">后退</a> <span >团团聚</span> </div> <div id="home-content-wrapper" > <div > <ul id="home-list" > </ul> </div> </div> </div>
如上面的代码,其实scroll的格式只是在需要做滚动的容器上加一个class为scroll的div在再在外面再加一层包装即可。这是一种固定的格式,接下来需要在scroll这div的里层外层的容器分别加上css,一个为min-height,另一个是height,这样就能保证滑动条不会跑到header上去了。
其次scrollview的初始化最好放在init里,如果放在reset里切换回来就会出现很多scroll-bar
当page转换回来的时候,如果这个滑动区滑过,那它还会在以前那个位置,这个时候就需要对滑动区进行重置。
this._scrollview.scrollTo(0);
2、page切换效果问题
另外对于page切换的效果问题,这个貌似开发指南里没有,caf框架貌似暂时只提供了默认的渐现切换效果,代码如下:
this.init = function(){
_super.init.apply(this, arguments);
//注册模板库
this._template.reg(runtime.getTplData("tuantju.tpl"));
this._deckPage.create(runtime.getWorkspace(), this, this._history);
this._deckPage.setUseAnimate(true);
this.reset();
};
在主app初始化时增加这一句 this._deckPage.setUseAnimate(true);
4、第三方库方面
在本地开发的sdk中,云应用平台是自动载入lib目录下的第三方库的,这样没法知晓依赖顺序,比如我这个应用需要用到jQuery和jQuery.tmpl,只能将两个文件按照依赖顺序写入同一个文件中,而在在线ide后需要在app.json配置文件中加入的lib项按顺序写入一个string。这样才能保证库的有效性,这个坑爹的东西折腾了我和正乐童鞋许久。
"lib": "jquery-1.6.1.min.js,tuantju.tpl,tuantju.lib",
5、关于云应用phonegap原生android系统app移植
放假时闲着无聊将花爷的云应用移植到了phonegap平台下,原生依赖caf框架的云应用移植会比较麻烦,因为caf没有phonegap下对应的框架,对于single-page的云应用还是很好移植的,就是将所有代码直接写在一个page下并且没有用caf提供的netInvoke远程代理请求的ajax请求而是直接用jQuery提供的ajax方法。这里要注意caf的netInvoke方法是通过远程代理的,而ajax是本地代理,所以需要在服务端开启rpc跨域:
<?php
header("Access-Control-Allow-Origin: *");
?>
下次会抽时间完整把我移植本地js到phonegap平台的东西写一下,这里就不赘述了。
6、关于api的获取
现在网站会提供很多开放的api以供开发者开发第三方应用。
下面的是国外收集的api集合:(http://www.blogjava.net/qixiangnj/archive/2007/10/31/157280.html)
但是国内貌似api开发的力度并不大,但是我们还是有办法的,比较文明的是联系他们,让他们提供api以便开发,那比较暴力的呢?可以用反编译android app的方法暴力的提取api,这是一个不错的方法,具体见我这篇博文(http://leyteris.iteye.com/blog/846036)
7、手机交互方面
其次是对于手机交互。由于手指触点很大,所以比如一个list-item不能太小,高度要达到65px;事先做好psd的交互设计图是关键。手机应用的UI甚至比应用本身功能还要重要。
如下设计稿是比较完整的,考虑到触点问题,将每一个可点击的item尽量在美观的情况下放大。对于输入框也最好在65px以上。
前辈还请以后多多指教啊~
public class eMyMapWnd2 extends eMyMapWnd {
public eMyMapWnd2(Context context) {
super(context);
}
@Override
public void OnGeometrySelected(int count) {
// 点选-----------------------------------------------------
int c = m_myMapWnd.GetMap().Selection().GetCount();
if (c > 0) {
eMyResultSet rs = m_myMapWnd.GetMap().Selection().GetAt(0);
rs.Reset();
int fieldCount = rs.GetLayer().GetFieldCount();
// 获得点选详情
while (rs.HasNext()) {
String text = "";
// 取x,y坐标
eMyPoint point = rs.GetGeometry().GetPointAt(0);
x = point.GetX();
y = point.GetY();
String xy = "逻辑坐标:( " + x + ") , (" + y + " )";
text += xy;
System.out.println(xy);
text += "\n";
eMyPoint2D point2D = m_myMapWnd.GetMap().MapToGeo(point);
x = point2D.GetX();
y = point2D.GetY();
xy = "物理坐标:( " + x + ") , (" + y + " )";
text += xy;
System.out.println(xy);
text += "\n";
// 其他信息:名称,id,城市,所在区,类别码,地理编码
for (int i = 0; i < fieldCount; i++) {
text += rs.GetLayer().GetFieldAt(i).GetName();
text += ":";
text += rs.GetString(i);
text += "\n";
}
Toast.makeText(this.getContext(), text, 9000).show();
// 分别取点的属性
System.out.println("------------------------------");
String s1 = rs.GetString((short) 0).toString();// 获得点名称
String s = s1.replaceAll("\\s1+", "");
System.out.println("名称:" + s);
s1 = rs.GetString((short) 1).toString();// 获得点ID
s = s1.replaceAll("\\s1+", "");
System.out.println("ID:" + s);
s1 = rs.GetString((short) 2).toString();// 获得点名称
s = s1.replaceAll("\\s1+", "");
System.out.println("城市:" + s);
s1 = rs.GetString((short) 3).toString();// 获得点名称
s = s1.replaceAll("\\s1+", "");
System.out.println("所在区:" + s);
s1 = rs.GetString((short) 4).toString();// 获得点名称
s = s1.replaceAll("\\s1+", "");
System.out.println("类别码:" + s);
s1 = rs.GetString((short) 5).toString();// 获得点名称
s = s1.replaceAll("\\s1+", "");
System.out.println("地理编码:" + s);
System.out.println("-------------------------------");
// String OBJNAME = rs.GetString("OBJNAME").toString();//
// 部件的名称
// String OBJCODE = rs.GetString("OBJCODE").toString();//
// 部件的编号
// String DEPTNAME1 =
// rs.GetString("DEPTNAME1").toString();// 部件的管辖部门
// String OBJPOS = rs.GetString("OBJPOS").toString();//
// 部件的??
// String BGCODE = rs.GetString("BGCODE").toString();//
// 部件的??
//
// System.out.println("OBJNAME=" + OBJNAME);
// System.out.println("OBJCODE=" + OBJCODE);
// System.out.println("DEPTNAME1=" + DEPTNAME1);
// System.out.println("OBJPOS=" + OBJPOS);
// System.out.println("BGCODE=" + BGCODE);
// string[] s = new string[7];
// s[0] = rs.GetString("OBJNAME");
// s[1] = rs.GetString("OBJCODE");
// s[2] = rs.GetString("DEPTNAME1");
// s[3] = rs.GetString("OBJPOS");
// s[4] = rs.GetString("BGCODE");
// s[5] = rs.GetGeometry().GetPointAt(0).x.ToString();
// s[6] = rs.GetGeometry().GetPointAt(0).y.ToString();
// ShangBaoView.getPoint(point[0].x, point[0].y);
// x作为int传值会出错,必须转化为string
// String x = String.valueOf(point[0].x);
// String y = String.valueOf(point[0].y);
}
}
}
protected Drawable boundCenterBottom(Drawable balloon) {
int markerWidth = balloon.getIntrinsicWidth();
int markerHeight = balloon.getIntrinsicHeight();
Rect srcRect = balloon.getBounds();
srcRect.offset(-markerWidth / 2, -markerHeight);
balloon.setBounds(srcRect);
return balloon;
}
@Override
public void OnDraw(Canvas canvas) {
if (!bDraw)
return;
Paint paint = new Paint();
eMyPoint pt = m_myMapWnd.GeoToPixel(new eMyPoint2D(loc_x, loc_y));
Point myScreenCoords = new Point((int) pt.GetX(), (int) pt.GetY());
// 转换当前地图位置到屏幕坐标点
// mv.getProjection().toPixels(gp1, myScreenCoords);
paint.setStrokeWidth(1);
paint.setARGB(255, 255, 0, 0);
paint.setStyle(Paint.Style.FILL);
@SuppressWarnings("unused")
Bitmap bm = BitmapFactory.decodeResource(getResources(),
R.drawable.location);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
// 加载两次图片资源
Drawable drawable = getResources().getDrawable(R.drawable.location);
// 这里调用mutate 做测试
Drawable drawable1 = getResources()
.getDrawable(R.drawable.location).mutate();
drawable.setBounds(myScreenCoords.x, myScreenCoords.y,
myScreenCoords.x + drawable.getIntrinsicWidth(),
myScreenCoords.y + drawable.getIntrinsicHeight());
drawable1.setBounds(0, 0, drawable1.getIntrinsicWidth(), drawable1
.getIntrinsicHeight());
// 位置的调节操作
boundCenterBottom(drawable);
drawable.draw(canvas);
canvas.restore();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
// 颜色的过滤
drawable1.setColorFilter(0x7f000000, PorterDuff.Mode.SRC_IN);
// 位移操作
canvas.translate(myScreenCoords.x, myScreenCoords.y);
// 倾斜操作
canvas.skew(-0.9F, 0.0F);
// 进行缩放
canvas.scale(1.0F, 0.5F);
boundCenterBottom(drawable1);
drawable1.draw(canvas);
// 这里清除颜色过滤
drawable1.clearColorFilter();
canvas.restore();
}
}
mms uri
table-----------------------------------------uri------------------(sql)
sms---------------------------Sms.CONTENT_URI-----------------"content://sms"(select * from sms;)
sms---------------------------Sms.Inbox.CONTENT_URI-----------"content://sms/inbox"(select * from sms where type=1)
sms---------------------------Sms.Sent.CONTENT_URI------------"content://sms/sent" (select * from sms where type=2)
sms---------------------------Sms.Draft.CONTENT_URI-----------"content://sms/draft"(select * from sms where type=3)
sms---------------------------Sms.Outbox.CONTENT_URI----------"content://sms/outbox"(select * from sms where type=4)
sms--------------------------------------------------"content://sms/undelivered"(select * from sms where type in(4,5,6))
sms--------------------------------------------------"content://sms/failed"(select * from sms where type =5)
sms--------------------------------------------------"content://sms/queued"(select * from sms where type =6)
raw---------------------------"content://sms/raw"-------------(select * from raw;)
attachments-------------------"content://sms/attachments"-----(select * from attachments)
表---Uri
media数据库分为内外 内部 卷标为:internal 外部卷标为:external 用*代替
query:
images --------------------MediaStroe.Images.Media.EXTERNAL_CONTENT_URI--------------"content://media/*/images/media"
images/_id ----------------MediaStroe.Images.Media.EXTERNAL_CONTENT_URI--------------"content://media/*/images/media/#"
thumbnails-----------------MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI---------"content://media/*/images/thumbnails"
thumbnails/_id------------MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI---------"content://media/*/images/thumbnails/#"
audio ---------------------MediaStore.Audio.Media.EXTERNAL_CONTENT_URI---------------"content://media/*/audio/media"
audio/_id -----------------MediaStore.Audio.Media.EXTERNAL_CONTENT_URI---------------"content://media/*/audio/media/#"
audio_genres---------------MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI--------------"content://media/*/audio/genres"
audio_genres/_id-----------MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI--------------"content://media/*/audio/genres/#"
audio_audio_playlists------MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI-----------"content://media/*/audio/playlists"
audio_audio_playlists/_id--MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI-----------"content://media/*/audio/playlists/#"
video----------------------MediaStore.Video.Media.EXTERNAL_CONTENT_URI---------------"content://media/*/video/media"
video/_id------------------MediaStore.Video.Media.EXTERNAL_CONTENT_URI---------------"content://media/*/video/media/#"
videothumbnails------------MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI----------"content://media/*/video/thumbnails"
videothumbnails/_id-------MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI----------"content://media/*/video/thumbnails/#"
artist_info----------------MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI-------------"content://media/*/audio/artist"
artist_info/_id------------MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI-------------"content://media/*/audio/artist/#"
album_info-----------------MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI--------------"content://media/*/audio/album"
album_info/_id-------------MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI--------------"content://media/*/audio/album/#"
album_art------------------ "content://media/*/audio/albumart/#"