写一下前些日子云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/#"