一般情况下,实现软件的布局可以有以下三种方式:布局文件(即****.xml文件)、编码的方式。。
而第三种就是我们这一边博客所要讲解的,通过网页实现软件的布局
原理:
网页实现界面:
1) 数据:应该来自于手机本身
webview 可以把一个java对象传递给网页,再让javascript去调用这个对象里面的方法
2) onload() javascript 代码调用java代码 java再调用javascript
明白2)中的流程是理解这种实现软件布局的方式的关键。。
以下通过一个例子来讲解:
程序运行截图:
实现步骤
1、在/assets/目录下导入网页布局文件.这里是index.html
下载链接为:
http://download.csdn.net/detail/caihongshijie6/6294611
2、main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <WebView android:id="@+id/webview" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
3、MainAcitivty
package com.njupt.htmlui1; import java.util.List; import org.json.JSONArray; import org.json.JSONObject; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.webkit.WebView; public class MainActivity extends Activity { private WebView webview; private ContactService service; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); webview = (WebView) findViewById(R.id.webview); service = new ContactService(); webview.addJavascriptInterface(new ContactPlugin(), "contact"); webview.getSettings().setJavaScriptEnabled(true); //以下一行代码表示王烨在本地 // webview.loadUrl("file:///android_asset/index.html"); //网页在服务器端 webview.loadUrl("http://192.168.1.105:8080/Web4/index.html"); } private class ContactPlugin { public void showcontacts() { try { List<ContactInfo> contactInfos = service.getContacts(); JSONArray jsonArray = new JSONArray(); int i; for (i = 0; i < contactInfos.size(); ++i) { JSONObject jsonObject = new JSONObject(); ContactInfo info = contactInfos.get(i); jsonObject.put("name", info.getName()); jsonObject.put("amount", info.getAmount()); jsonObject.put("phone", info.getPhone()); jsonArray.put(jsonObject); } String json = jsonArray.toString(); webview.loadUrl("javascript:show(" + json + ")"); } catch (Exception e) { e.printStackTrace(); } } public void call(String phone) { Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone)); startActivity(intent); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
4、ContactInfo
package com.njupt.htmlui1; public class ContactInfo { private String name; private long amount; private String phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public long getAmount() { return amount; } public void setAmount(long amount) { this.amount = amount; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public ContactInfo(String name, long amount, String phone) { super(); this.name = name; this.amount = amount; this.phone = phone; } public ContactInfo() { super(); } @Override public String toString() { return "ContactInfo [name=" + name + ", amount=" + amount + ", phone=" + phone + "]"; } }
5、ContactService
package com.njupt.htmlui1; import java.util.ArrayList; import java.util.List; public class ContactService { public List<ContactInfo> getContacts(){ List<ContactInfo> contacts = new ArrayList<ContactInfo>(); contacts.add(new ContactInfo("zzt", 40000, "123456")); contacts.add(new ContactInfo("lss", 42000, "223457")); contacts.add(new ContactInfo("liuyifei", 44000, "3345678")); contacts.add(new ContactInfo("allen", 45000, "499999")); return contacts; } }
6、记得在AndroidManifest.xml清单文件中注册上相应的权限
<uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.INTERNET"/>
原理图:
1)
2)
代码如下:
1、在drawable目录下导入要演示的图片
2、main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="matrix" android:src="/blog_article/@drawable/a/index.html" /> </LinearLayout>
3、MainActivity
package com.njupt.drag_scale1; import android.app.Activity; import android.graphics.Matrix; import android.graphics.PointF; import android.os.Bundle; import android.util.FloatMath; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; public class MainActivity extends Activity { /** Called when the activity is first created. */ private ImageView iv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) findViewById(R.id.iv); iv.setOnTouchListener(new MyOnTouchListener()); } private final class MyOnTouchListener implements OnTouchListener{ private PointF startPoint = new PointF();//初始点 private Matrix mCurrentMatrix = new Matrix();//图片初始的matrix值 private Matrix mMatrix = new Matrix();//来一个临时的matrix private PointF midPointF;//中心点 private float midDistance;//两点间的距离 private int type = 0; private final static int DRAG = 1; private final static int SCALE = 2; public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub int action = event.getAction()&MotionEvent.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN://手指按下 float x = event.getX(); float y = event.getY(); startPoint.set(x, y); mCurrentMatrix.set(iv.getImageMatrix());//图片没有移动的位置 type = DRAG; break; case MotionEvent.ACTION_POINTER_1_DOWN://屏幕上有一根手指,再按下一根手指 mCurrentMatrix.set(iv.getImageMatrix());//图片没有缩放的大小 midPointF = getMidPointF(event); midDistance = getMidDistance(event); type = SCALE; break; case MotionEvent.ACTION_MOVE://手指移动 if(type == DRAG){ mMatrix.set(mCurrentMatrix); float dx = event.getX() - startPoint.x; float dy = event.getY() - startPoint.y; mMatrix.postTranslate(dx, dy); }else if(type == SCALE){ mMatrix.set(mCurrentMatrix); float distance = getMidDistance(event);//得到当前两个手指间的距离 float sx = distance/midDistance;//得到缩放的倍数 mMatrix.postScale(sx, sx, midPointF.x, midPointF.y); } break; case MotionEvent.ACTION_UP://手指弹起 case MotionEvent.ACTION_POINTER_1_UP://弹起一根手指,屏幕上还有一根手指 type = 0; break; default: break; } iv.setImageMatrix(mMatrix); return true; } } //得到中心点 private PointF getMidPointF(MotionEvent event){ float x = (event.getX(1) + event.getX(0))/2; float y = (event.getY(1) + event.getY(0))/2; return new PointF(x, y); } //计算两点间的距离 private float getMidDistance(MotionEvent event){ float dx = event.getX(1) - event.getX(0); float dy = event.getY(1) - event.getY(0); return FloatMath.sqrt(dx*dx + dy*dy); } }
前篇:《MyGui笔记(1)建立第一个工程》
本篇:创建控件的方法要传入控件类型和控件皮肤,这里简单记录下所有控件的类型和皮肤。
环境:MyGui3.2.0(OpenGL平台)
从WidgetManager::initialise()可以看到所有的控件类型为下:
控件类型 控件说明 控件备注 Button 按钮 Canvas 画布 显示纹理 ComboBox 下拉框 派生自EditBox,可设置是否可编辑 DDContainer 拖曳容器 EditBox 编辑框 ItemBox 项框 派生自DDContainer,支持拖曳 ListBox 列表框 MenuBar 菜单栏 MenuControl 菜单控件 MenuItem 菜单项 MultiListBox 多行列表框 MultiListItem 多行列表项 PopupMenu 弹出菜单 ProgressBar 进度条 ScrollBar 滚动条 ScrollView 滚动视图 ImageBox 图像框 TextBox 文本框 TabControl 标签控件 TabItem 标签项 Widget 控件 Window 窗口 这些控件的关系图如下:
第一张:
第二张:
第三张:
再来看Widget::_initialise(WidgetStyle _style, const IntCoord& _coord, const std::string& _skinName, Widget* _parent, ICroppedRectangle* _croppedParent, const std::string& _name)如何加载皮肤,代码如下:
2
3
4
5
6
7
ResourceLayout* templateInfo = nullptr;
if (LayoutManager::getInstance().isExist(_skinName))
templateInfo = LayoutManager::getInstance().getByName(_skinName);
else
skinInfo = SkinManager::getInstance().getByName(_skinName);
可以看到先判断皮肤是否来自布局管理器,否则的话再从皮肤管理器进行获取,亦即先从MyGUI_BlueWhiteTemplates.xml获取,再从MyGUI_BlueWhiteSkins.xml获取。MyGUI_BlueWhiteTemplates.xml内容部分为下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<Widget type="Widget" skin="PanelEmpty" position="15 10 68 49" name="Root">
<Property key="Snap" value="true"/>
<Property key="Movable" value="false"/>
<UserString key="LE_TargetWidgetType" value="Window"/>
<Widget type="Widget" skin="CaptionEmptySkin" position="0 0 68 28" align="HStretch Top">
<Widget type="TextBox" skin="TextBox" position="2 3 62 24" align="HStretch Top" name="Caption">
<Property key="TextColour" value="0 0 0"/>
<Property key="TextAlign" value="Center"/>
<Property key="FontName" value="Default"/>
</Widget>
</Widget>
<Widget type="Widget" skin="WindowFrameSkin" position="0 28 68 20" align="Stretch">
<Widget type="Widget" skin="ClientTileSkin" position="4 2 58 12" align="Stretch" name="Client"/>
</Widget>
</Widget>
</Resource>
<Resource type="ResourceLayout" name="Button" version="3.2.0">
<Widget type="Widget" skin="ButtonSkin" position="20 25 29 26" name="Root">
<Property key="FontName" value="Default"/>
<Property key="TextAlign" value="Center"/>
<UserString key="LE_TargetWidgetType" value="Button"/>
</Widget>
</Resource>
每个可视控件都有一个Resource type="ResourceLayout"的节点来描述该控件的布局,由上内容也可以看出某些控件是其他基本控件进行组合而成的。做为根子控件带有属性name="Root",其子节点包含属性描述、子控件描述等等。注意一点<UserString key="LE_TargetWidgetType" value="Button"/>
表明这个控件所使用的控件类型为Button。所有的布局控件为下:
MyGUI_BlueWhiteSkins.xml内容部分为下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<BasisSkin type="SubSkin" offset="0 0 7 7" align="Left Top">
<State name="disabled" offset="136 2 7 7"/>
<State name="normal" offset="136 29 7 7"/>
<State name="highlighted" offset="136 56 7 7"/>
<State name="pushed" offset="136 83 7 7"/>
<State name="disabled_checked" offset="136 110 7 7"/>
<State name="normal_checked" offset="136 137 7 7"/>
<State name="highlighted_checked" offset="136 164 7 7"/>
<State name="pushed_checked" offset="136 191 7 7"/>
</BasisSkin>
<BasisSkin type="SubSkin" offset="7 0 14 7" align="HStretch Top">
<State name="disabled" offset="143 2 14 7"/>
<State name="normal" offset="143 29 14 7"/>
<State name="highlighted" offset="143 56 14 7"/>
<State name="pushed" offset="143 83 14 7"/>
<State name="disabled_checked" offset="143 110 14 7"/>
<State name="normal_checked" offset="143 137 14 7"/>
<State name="highlighted_checked" offset="143 164 14 7"/>
<State name="pushed_checked" offset="143 191 14 7"/>
</BasisSkin>
……
</Resource>
可以看出记录的是控件皮肤的构成,size属性指定控件的大小,texture指定控件所在的纹理图。含有多个SubSkin子节点,代表此皮肤的构成,比如这里的ButtonSkin皮肤是由九宫格拼接的,则有9个SubSkin子节点,另外还有个SimpleText来指定按钮上的文本位置。用SkinEditor.exe打开纹理文件MyGUI_BlueWhiteSkins.png,在Skins标签里选择ButtonSkin,切换到Regions标签,可看到具体的子皮肤构成,如下图所示:
关于MyGUI_BlueWhiteImages.xml文件的作用,这个文件全部内容如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<MyGUI type="Resource" version="1.1">
<Resource type="ResourceImageSet" name="MultiListButtonImage">
<Group name="Icons" texture="MyGUI_BlueWhiteSkins.png" size="12 10">
<Index name="None">
<Frame point="74 185"/>
</Index>
<Index name="Up">
<Frame point="74 198"/>
</Index>
<Index name="Down">
<Frame point="74 211"/>
</Index>
</Group>
</Resource>
</MyGUI>
只定义了一个ResourceImageSet资源图像集,名称为MultiListButtonImage,这个名称被MyGUI_BlueWhiteTemplates.xml里面的内容进行引用,内容如下:
2
3
4
5
6
7
8
9
10
11
12
13
<Widget type="Widget" skin="MultiListButtonSkin" position="20 25 45 21" name="Root">
<Property key="FontName" value="Default"/>
<Property key="TextAlign" value="Center"/>
<UserString key="LE_TargetWidgetType" value="Button"/>
<Widget type="ImageBox" skin="ImageBox" position="29 4 12 10" align="Right VCenter" name="Image">
<Property key="ImageResource" value="MultiListButtonImage"/>
<Property key="ImageGroup" value="Icons"/>
<Property key="ImageName" value="Down"/>
<Property key="NeedMouse" value="false"/>
</Widget>
</Widget>
</Resource>
MultiListButton多行列表按钮采用了这个图像集,用ImageEditor.exe打开MyGUI_BlueWhiteImages.xml文件,在Images标签选择MultiListButtonImage,切换到Indexes标签,可看到索引到的是空白图像、上箭头图像、下箭头图像,如下图所示:
另外,MyGUI_BlueWhiteTheme.xml文件,内容如下:
2
3
4
5
6
<MyGUI type="List">
<List file="MyGUI_BlueWhiteImages.xml"/>
<List file="MyGUI_BlueWhiteSkins.xml"/>
<List file="MyGUI_BlueWhiteTemplates.xml"/>
</MyGUI>
这个主题文件列出了该主题所需要使用到的另外文件,分别是MyGUI_BlueWhiteImages.xml、MyGUI_BlueWhiteSkins.xml和MyGUI_BlueWhiteTemplates.xml,这些都已在上面进行大概介绍过了。
下一篇继续……