Android App开发基础(3)——App的设计规范

3 App的设计规范

本节介绍了App工程的源码设计规范,首先App将看得见的界面设计与看不见的代码逻辑区分开,然后利用XML标记描绘应用界面,同时使用Java代码书写程序逻辑,从而形成App前后端分离的设计规约,有利于提高App集成的灵活性。

3.1 界面设计与代码逻辑

手机的功能越来越强大,某种意义上相当于微型电脑,比如打开一个电商App,仿佛是在电脑上浏览网站。网站分为用户看得到的网页,以及用户看不到的Web后台;App也分为用户看得到的界面,以及用户看不到的App后台。虽然Android允许使用Java代码描绘界面,但不提倡这么做,推荐的做法是将界面设计从Java代码剥离出来,通过单独的XML文件定义界面布局,就像网站使用HTML文件定义网页那样。
直观地看,网站的前后端分离设计,App的前后端分离设计如图所示
网站的前后端分离设计

App的前后端分离设计

把界面设计与代码逻辑分开,不仅参考了网站的Web前后端分离,还有下列几点好处。

(1)使用XML文件描述App界面,可以很方便地在Android Studio上预览界面效果。比如新创建的App项目,默认首页布局为activity_main.xml,单击界面右上角的Design按钮,即可看到如图所示的预览界面。如果XML文件修改了Hello World的文字内容,立刻就能在预览区域观看最新界面。倘若使用Java代码描绘界面,那么必须运行App才能看到App界面,无疑费时许多。
XML文件的预览界面

(2)一个界面布局可以被多处代码复用,比如看图界面,既能通过商城购物代码浏览商品图片,也能通过商品评价代码浏览买家晒单。

(3)反过来,一段Java代码也可能适配多个界面布局,比如手机有竖屏与横屏两种模式,默认情况App采用同一套布局,然而在竖屏时很紧凑的界面布局,切换到横屏往往变得松垮乃至变形。

竖屏时很紧凑的界面布局:
竖屏时候的界面布局
 
 横屏时候的界面布局:
横屏时候的界面布局

鉴于竖屏与横屏遵照一样的业务逻辑,仅仅是屏幕方向不同,若要调整的话,只需分别给出竖屏时候的界面布局,以及横屏时候的界面布局。因为用户多数习惯竖屏浏览,所以res/layout目录下放置的XML文件默认为竖屏规格,另外在res下面新建名为layout-land的目录,用来存放横屏规格的XML文件land是landscape的缩写,意思是横向,Android把layout-land作为横屏XML的专用布局目录。然后在layout-land目录创建与原XML同名的XML文件,并重新编排界面控件的展示方位,调整后的横屏界面如图所示,从而有效适配了屏幕的水平方向。

 采用另一个XML文件的横屏布局

3.2 利用XML标记描绘应用界面

在上一篇文章“1.2 App的开发语言”末尾,给出了安卓控件的XML定义例子,如下所示:

<TextViewandroid:id="@+id/tv_hello"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!" />

注意到TextView标签以“<”开头,以“/>”结尾,为何尾巴多了个斜杆呢?要是没有斜杆,以左右尖括号包裹标签名称,岂不更好?其实这是XML的标记规范,凡是XML标签都由标签头与标签尾组成,标签头以左右尖括号包裹标签名称,形如“”;标签尾在左尖括号后面插入斜杆,以此同标签头区分开,形如“”。标签头允许在标签名称后面添加各种属性取值,而标签尾不允许添加任何属性,因此上述TextView标签的完整XML定义是下面这样的:

<TextViewandroid:id="@+id/tv_hello"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!">
</TextView>

考虑到TextView仅仅是个文本视图,其标签头和标签尾之间不会插入其他标记,所以合并它的标签头和标签尾,也就是让TextView标签以“/>”结尾,表示该标签到此为止。

然而不是所有情况都能采取简化写法,简写只适用于TextView控件这种末梢节点。好比一棵大树,大树先有树干,树干分岔出树枝,一些大树枝又分出小树枝,树枝再长出末端的树叶。一个界面也是先有根节点(相当于树干),根节点下面挂着若干布局节点(相当于树枝),布局节点下面再挂着控件节点(相当于树叶)。因为树叶已经是末梢了,不会再包含其他节点,所以末梢节点允许采用“/>”这种简写方式。

譬如下面是个XML文件的布局内容,里面包含了根节点、布局节点,以及控件节点:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 这是个线性布局, match_parent意思是与上级视图保持一致--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><!-- 这是个文本视图,名字叫做tv_hello,显示的文字内容为“Hello World!” --><TextViewandroid:id="@+id/tv_hello"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!" /></LinearLayout>
</LinearLayout>

上面的XML内容,最外层的LinearLayout标签为该界面的根节点,中间的LinearLayout标签为布局节点,最内层的TextView为控件节点。由于根节点和布局节点都存在下级节点,因此它们要有配对的标签头与标签尾,才能将下级节点包裹起来。根节点其实是特殊的布局节点,它的标签名称可以跟布局节点一样,区别之处在于下列两点:

(1)每个界面只有一个根节点,却可能有多个布局节点,也可能没有中间的布局节点,此时所有控件节点都挂在根节点下面。

(2)根节点必须配备“xmlns:android=“http://schemas.android.com/apk/res/android””,表示指定 XML内部的命名空间,有了这个命名空间,Android Studio会自动检查各节点的属性名称是否合法,如果不合法就提示报错。至于布局节点就不能再指定命名空间了。

有了根节点、布局节点、控件节点之后,XML内容即可表达丰富多彩的界面布局,因为每个界面都能划分为若干豆腐块,每个豆腐块再细分为若干控件罢了。三种节点之外,尚有“”这类注释标记,它的作用是包裹注释性质的说明文字,方便其他开发者理解此处的XML含义。

3.3 使用Java代码书写程序逻辑

在XML文件中定义界面布局,已经明确是可行的了,然而这只是静态界面,倘若要求在App运行时修改文字内容,该当如何是好?倘若是动态变更网页内容,还能在HTML文件中嵌入JavaScript代码,由js片段操作Web控件。但Android的XML文件仅仅是布局标记,不能再嵌入其他语言的代码了,也就是说,只靠XML文件自身无法动态刷新某个控件。

XML固然表达不了复杂的业务逻辑,这副重担就得交给App后台的Java代码了。Android Studio每次创建新项目,除了生成默认的首页布局activity_main.xml之外,还会生成与其对应的代码文件 MainActivity.java。赶紧打开MainActivity.java,看看里面有什么内容,该Java文件中MainActivity类的内容如下所示:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}

可见MainActivity.java的代码内容很简单,只有一个MainActivity类,该类下面只有一个onCreate方
法。注意onCreate内部的setContentView方法直接引用了布局文件的名字activity_main,该方法的意思是往当前活动界面填充activity_main.xml的布局内容。现在准备在这里改动,把文字内容改成中文。

首先打开activity_main.xml,在TextView节点下方补充一行android:id=“@+id/tv_hello”,表示给它起个名字编号;然后回到MainActivity.java,在setContentView方法下面补充几行代码,具体如下:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 当前的页面布局采用的是res/layout/activity_main.xmlsetContentView(R.layout.activity_main);// 获取名叫tv_hello的TextView控件,注意添加导包语句import android.widget.TextView;TextView tv_hello = findViewById(R.id.tv_hello);// 设置TextView控件的文字内容tv_hello.setText("你好,世界!!!");}
}

新增的两行代码主要做了这些事情:先调用findViewById方法,从布局文件中取出名为tv_hello的
TextView控件;再调用控件对象的setText方法,为其设置新的文字内容。
代码补充完毕,重新运行测试App,发现应用界面变成了如图所示的样子。
在这里插入图片描述

可见使用Java代码成功修改了界面控件的文字内容。

本笔记参考于[B站动脑学院],仅作学习用途,方便随时查看。 参考资料:2022 最新 Android
基础教程,从开发入门到项目实战,看它就够了,更新中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/649013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fastbee开源物联网项目RoadMap

架构优化 代码简化业务&协议解耦关键组件支持横向拓展网络协议支持横向拓展&#xff0c;包括&#xff1a;mqtt broker,tcp,coap,udp,sip等协议插件化编码脚本化业务代码模版化消息总线 功能优化 网关/子网关&#xff1a;上线&#xff0c;绑定&#xff0c;拓扑&#xff0…

快毕业了,同学纪念册如何制作出高级感

​快毕业了&#xff0c;这是一个充满回忆和感慨的时刻。同学们都想制作一本高级感的同学纪念册&#xff0c;留住这段美好的时光。但是自己着手制作的纪念册太丑&#xff0c;那不出手怎么办&#xff1f;那你就问对人了&#xff0c;我给大家演示几个步骤&#xff0c;需要的可以学…

【java】常见的面试问题

目录 一、异常 1、 throw 和 throws 的区别&#xff1f; 2、 final、finally、finalize 有什么区别&#xff1f; 3、try-catch-finally 中哪个部分可以省略&#xff1f; 4、try-catch-finally 中&#xff0c;如果 catch 中 return 了&#xff0c;finally 还会执行吗&#…

ambari hdp 企业级安装实战

一 配置部署环境 1.1 检查操作系统 1.1.1 检查操作系统版本 cat /etc/redhat-release1.1.2 检查操作系统默认语言 $ echo $LANG en_US.UTF-8若操作系统默认语言为en_US.UTF-8,则进入下一步。 若操作系统默认语言非en_US.UTF-8,则执行以下步骤: # 将默认语言由中文切换为…

瀑布流布局 (初版)

瀑布流布局 文章目录 瀑布流布局前言1. 背景2. 点⬇️&#x1f517;去体验效果如下图所示&#xff1a; 一、初版waterfall布局和问题暴露&#xff1f;1.效果图如下&#xff1a;2.暴露问题如下图所示&#xff1a;第一张问题图&#xff1a;第二张问题图&#xff1a; 3.HTML代码如…

有效的字母异位词

42. 有效的字母异位词https://leetcode.cn/problems/valid-anagram/ 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异位词。 示例 1: 输入: s …

go语言Map与结构体

1. Map map是一种无序的基于key-value的数据结构&#xff0c;Go语言中的map是引用类型&#xff0c;必须初始化才能使用。 1.1. map定义 Go语言中 map的定义语法如下 map[KeyType]ValueType其中&#xff0c; KeyType:表示键的类型。ValueType:表示键对应的值的类型。map类型的…

maven组件升级报错经验汇总

1. NosuchMethodError org.springframework.beans.factory.support.genericBeanDefinition(xxxxx) 2. ClassNotFoundException: org.springframework.boot.SpringApplication 可能冲突的依赖是&#xff1a; <dependency><groupId>org.springframework.boot</g…

NodeJS Express实现所有页面Http访问重定向跳转为Https

要在Node.js Express中实现所有页面从HTTP访问跳转到HTTPS&#xff0c;你可以使用重定向中间件。以下是一个简单的示例&#xff1a; 1. 首先&#xff0c;确保你已经安装了Express和express-redirect中间件。如果没有&#xff0c;你可以通过npm进行安装&#xff1a; npm insta…

8.6 代理设计模式

文章目录 一、代理模式&#xff08;Proxy Pattern&#xff09;概述二、代理模式和观察者设计模式三、模式结构四、协作角色五、实现策略六、相关模式七、示例八、应用 一、代理模式&#xff08;Proxy Pattern&#xff09;概述 代理模式是一种设计模式&#xff0c;它通过引入一个…

智能体AI Agent的极速入门:从ReAct到AutoGPT、QwenAgent、XAgent

前言 如这两天在微博上所说&#xff0c;除了已经在七月官网上线的AIGC模特生成系统外&#xff0c;我正在并行带多个项目组 第二项目组&#xff0c;论文审稿GPT第2版的效果已经超过了GPT4&#xff0c;详见《七月论文审稿GPT第2版&#xff1a;用一万多条paper-review数据集微调…

跨语言编程:在C#应用程序中调用Python

应用场景 众所周知&#xff0c;Python在深度学习中占有绝对优势。而C#语言的优势在各种后端应用开发&#xff0c;特别是工业领域。当我们使用 C# 开发应用程序时&#xff0c;可能需要调用 Python 代码来实现某些功能。这时&#xff0c;我们可以使用 Python.NET 或 IronPython 等…

69.x 的平方根(力扣LeetCode)

69.x 的平方根&#xff08;力扣LeetCode&#xff09; 题目描述 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 注意&#xff1a;不允许使用任何内置指数函数和算符&…

Vue-38、Vue中插件使用

1、新建plugins.js文件 2、可以在plugins.js 定义全局过滤器 定义全局指令 定义混入 给vue原型上添加一个方法 export default {install(Vue){console.log("install",Vue);//全局过滤器Vue.filter(mySlice,function (value) {return value.slice(0,4)});//定义全局…

遇到这3种接口测试问题,其实,你可以这么办~

作为整个软件项目的必经环节&#xff0c;软件测试是不可缺少的“查漏补缺”环节。而作为软件测试中的重要一环——接口测试&#xff0c;几乎串联了整个项目所有的输入和输出环节。 前几年&#xff0c;我在做后端测试时&#xff0c;接触最多的正是接口测试。基于此&#xff0c;…

操作系统-进程通信(共享存储 消息传递 管道通信 读写管道的条件)

文章目录 什么是进程通信为什么进程通信需要操作系统支持共享存储消息传递直接通信方式间接通信方式 管道通信小结注意 什么是进程通信 分享吃瓜文涉及到了进程通信 进程通信需要操作系统支持 为什么进程通信需要操作系统支持 进程不能访问非本进程的空间 当进程P和Q需要…

美易平台:芯片生产商Cerebras Systems考虑最快今年IPO

据知情人士透露&#xff0c;硅谷芯片制造初创公司Cerebras Systems Inc.正考虑在今年下半年进行首次公开募股&#xff08;IPO&#xff09;。如果成功上市&#xff0c;这家人工智能&#xff08;AI&#xff09;超级计算机生产商的估值将超过其2021年融资时的40亿美元估值。目前&a…

【DeepLearning-3】前馈(feed-forward)神经网络层

类定义 class FeedForward(nn.Module): FeedForward 类继承自 nn.Module&#xff0c;nn.Module是PyTorch中所有神经网络模块的基类。nn.Module允许您创建自己的神经网络层。 nn.Module 是构建所有神经网络层和模型的基类。当创建一个类继承自 nn.Module时&#xff0c;意味着你…

JavaScript中有哪些函数类型

JavaScript中的函数类型有很多种&#xff0c;下面列出了一些常见的函数类型及其示例&#xff1a; 一元函数&#xff08;Unary Functions&#xff09;&#xff1a;只接收一个参数的函数。 一元函数是指函数方程中只包含一个自变量的函数。例如&#xff0c;函数yF(x)是一元函数&…

幻兽帕鲁服务器数据备份

搭建幻兽帕鲁个人服务器&#xff0c;最近不少用户碰到内存不足、游戏坏档之类的问题。做好定时备份&#xff0c;才能轻松快速恢复游戏进度 这里讲一下如何定时将服务器数据备份到腾讯云轻量对象存储服务&#xff0c;以及如何在有需要的时候进行数据恢复。服务器中间的数据迁移…