Android-UI开发指南
- Android Studio调试
- UI设计
- UI框架
- 布局Layout
- 文本框
- 按钮
- 日期时间控件
- 其它常见小部件
- Menu菜单
- android的活动
- Activity基本概念
- Activity的生命周期
- Activity栈
- 创建Activity
- 管理Activity
- Activity间传递数据
- Fragment
- Adapter适配器
- RecyclerView
- RecyclerView Adapter(适配器)
- 事件
- setOnItemLongClickListener()方法
- AndroidManifest.xml
- 基本结构
- 权限声明
- 应用程序组件声明
- 其他配置项
- 网络与服务 && webview
- 网络和服务 && HttpUrlConnection
- 网络和服务 && JSON数据解析
- 网络和服务 && UI线程
- 网络和服务 && AsyncTask
- 事件处理的几种方法
- Toast提示框
- 对话框
- 自定义对话框
- 网络和服务
- 意图和广播 && 广播的发送
- 意图和广播 && 广播接收器
- 调试之 Log和LogCat的详解
- 为什么使用Log而不使用System.out
- LogCat中的5个级别日志级别控制
- Android Log调试信息的显示
- 具体该调用哪个方法添加什么类型的调试信息?
- adb查看Log日志
- Logcat命令列表:
- ListView 信息展示
- 动态添加View之addView
- -- 通过addView的方式动态向布局中添加View了。
- -- addView的使用
- -- 在LinearLayout中的使用:
Android Studio调试
UI设计
UI框架
布局Layout
1.线性布局 LinearLayout
- 排列方式(orientation) 有横竖两种方向的,水平和垂直
在xml文件中:
android:orientation="vertical" // 垂直排列
android:orientation="horizontal" // 水平排列
在java代码中:
linearLayout.setOrientation(LinearLayout.VERTICAL); // 设置垂直排列
linearLayout.setOrientation(LinearLayout.HORIZONTAL);// 设置水平排列
- 这里需要注意:
android:orientation="vertical",子View使用layout_gravity在垂直方向上的设定无效
android:orientation="horizontal",子View使用layout_gravity在水平方向上的设定无效
- 摆放位置(gravity/layout_gravity)
gravity是针对当前 控件里面 内容 的摆放,
如果是容器,则针对的是容器里面子view的摆放;
如果是控件,则针对的是控件里面内容的摆放。
layout_gravity是指当前控件在 父控件里面 的摆放位置,
不过需要注意的一点是父控件设置的gravity的级别要低于子控件设置的layout_gravity。
- 权重(layout_weight)
layout_weight
在LinearLayout布局之中,权重也是一个很重要的属性。简单来说就是按比例来分配控件占用父控件的大小。
若C-child表示子布局声明的大小,B-blank表示剩余布局的大小,P-percent表示子布局占据父布局剩余布局的比例,则子布局最终的实际大小R-reality为:
R = C + B * P
我们来按照公式来计算
R = C + B * P = 0dp + (B-0dp-0dp) * (1/2) = (1/2)B
也就是父布局的1/2。
- weightSum
LinearLayout有一个权重数量的标记:weightSum。
在LinearLayout中没有声明weightSum时,
默认的就是各个控件权重的总和。 - 0dp与wrap_content
谷歌官方建议子布局的layout_width使用0dp,来分比例显示布局,
和wrap_content大同小异,当使用layout_weight时,都表示占据剩余宽度或高度的比重。
但两者有明显区别。
使用0dp时,要考虑所分配的布局宽度是否小于控件实际宽度
- B是剩余布局的大小 = 父布局大小 - 子控件大小之和
B = C - (C + C) = -C;
R = C + B * P = C + (-C) * (1/3) = 2/3C
这里的C就是父布局的大小也就是match_parent。
三个属性都用来适应视图的 水平或 垂直大小,
一个以视图的 内容或尺寸 为基础的 布局比
精确地指定视图范围更加方便。
1)fill_parent
设置一个构件的布局为fill_parent将强制性地使构件扩展,
以填充布局单元内尽可能多的空间。
这跟Windows控件的dockstyle属性大体一致。
设置一个顶部布局或控件为fill_parent将强制性让它布满整个屏幕。
2) wrap_content
设置一个视图的尺寸为wrap_content将强制性地使视图扩展以显示全部内容。
以TextView和ImageView控件为例,
设置为wrap_content将完整显示其内部的文本和图像。
布局元素将根据内容更改大小。
设置一个视图的尺寸为wrap_content大体等同于设置Windows控件的Autosize属性为True。
3)match_parent
Android2.2中match_parent和fill_parent是一个意思 .
两个参数意思一样,match_parent更贴切,
于是从2.2开始两个词都可以用。
那么如果考虑低版本的使用情况你就需要用fill_parent了
文本框
按钮
日期时间控件
其它常见小部件
Menu菜单
android的活动
Activity基本概念
Activity的生命周期
Activity栈
创建Activity
管理Activity
Activity间传递数据
Fragment
Adapter适配器
负责将数据绑定到View上
RecyclerView
RecyclerView是用于展示大量数据集合的高效控件
RecyclerView Adapter(适配器)
是Android开发中用于管理RecyclerView的重要组件之一。
主要完成以下几个任务:
创建ViewHolder:在RecyclerView中,每个子项都需要一个ViewHolder来显示数据。Adapter负责创建和管理ViewHolder对象,通常通过继承RecyclerView.Adapter类来实现自定义的Adapter,并重写其中的方法。
绑定数据到ViewHolder:Adapter中的onBindViewHolder()方法负责将数据与ViewHolder进行绑定。在该方法中,您可以获取当前位置的数据,并将其设置到ViewHolder的各个视图中。
定义Item视图类型:如果RecyclerView中存在多个不同的Item视图类型,Adapter可以通过重写getItemViewType()方法返回不同的视图类型,以便RecyclerView能够正确渲染不同类型的子项。
确定子项数量:Adapter需要实现getItemCount()方法来指定RecyclerView中子项的数量。
响应用户交互:通过Adapter可以为RecyclerView的子项添加点击事件、长按事件等交互操作。
总之,RecyclerView Adapter充当了RecyclerView与数据之间的桥梁,负责将数据展示到RecyclerView中,并处理与用户交互相关的操作。
事件
setOnItemLongClickListener()方法
LinearLayout mainLayout = new LinearLayout(this);
mainLayout.setOrientation(LinearLayout.VERTICAL);
mainLayout.setBackgroundColor(0xFFF6F8FB);
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
0,
1
));
mainLayout.addView(frameLayout);
LinearLayout tabLayout = new LinearLayout(this);
tabLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip2px(88)
));
tabLayout.setOrientation(LinearLayout.HORIZONTAL);
tabLayout.setPadding(dip2px(15), 0, dip2px(15), dip2px(15));
tabLayout.setBackgroundResource(R.drawable.sp_main_tab_n);
mainLayout.addView(tabLayout);
// 添加第一个Tab
FrameLayout tab1FrameLayout = new FrameLayout(this);
tab1FrameLayout.setLayoutParams(new LinearLayout.LayoutParams(
0,
LinearLayout.LayoutParams.MATCH_PARENT,
1
));
tabLayout.addView(tab1FrameLayout);
LinearLayout tab1Layout = new LinearLayout(this);
tab1Layout.setId(R.id.tabLin5);
tab1Layout.setLayoutParams(new LinearLayout.LayoutParams(
dip2px(64),
dip2px(56)
));
tab1Layout.setOrientation(LinearLayout.VERTICAL);
tab1Layout.setGravity(Gravity.CENTER);
tab1Layout.setBackgroundResource(R.drawable.sp_main_tab);
tab1FrameLayout.addView(tab1Layout);
ImageView tab1ImageView = new ImageView(this);
tab1ImageView.setId(R.id.iv5);
tab1ImageView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
));
tab1ImageView.setImageResource(R.drawable.sp_home_tab5);
tab1Layout.addView(tab1ImageView);
TextView tab1TextView = new TextView(this);
tab1TextView.setId(R.id.tv_tab5);
tab1TextView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
));
tab1TextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
tab1TextView.setGravity(Gravity.CENTER);
tab1TextView.setTextColor(ContextCompat.getColor(this, R.color.s_main_tab_text));
tab1TextView.setText(R.string.Contacts);
tab1Layout.addView(tab1TextView);
// 设置TabLayout置底显示
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabLayout.getLayoutParams();
params.gravity = Gravity.BOTTOM;
tabLayout.setLayoutParams(params);
// 添加其他Tab的代码类似,省略
setContentView(mainLayout);
private int dip2px(float dpValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
AndroidManifest.xml
定义应用程序配置信息
提供了应用程序与 Android 系统之间的通信接口。
基本结构
AndroidManifest.xml 是一个 XML 文件,位于 Android 项目的根目录下的 app/src/main/ 目录中。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<!-- Application components and settings go here -->
</manifest>
<manifest>:该标签是 AndroidManifest.xml 的根元素。
xmlns:android="http://schemas.android.com/apk/res/android":这是命名空间声明,用于引用 Android 的命名空间。
package="com.example.myapp":这里指定了应用程序的包名。
权限声明
可以声明应用程序需要的各种权限。例如,访问设备的摄像头、网络连接、读写存储等。权限声明
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
这些权限声明允许你的应用程序执行相关操作,并保证用户在安装应用时能够知晓。
应用程序组件声明
Android 应用程序由多个组件构成,
如活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。
在 AndroidManifest.xml 中声明这些组件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application
android:icon="@drawable/app_icon"
android:label="@string/app_name">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService" />
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<provider android:name=".MyProvider"
android:authorities="com.example.myapp.provider" />
</application>
</manifest>
声明了
活动(MainActivity)
服务(MyService)、
广播接收器(MyReceiver)
内容提供者(MyProvider)
活动声明中使用了 标签来指定活动的入口点,
服务声明没有指定任何过滤器,
广播接收器声明中定义了接收到 BOOT_COMPLETED 广播时接收该广播的操作,
内容提供者声明中定义了内容提供者的权限(authorities属性)。
其他配置项
除了上述内容之外,AndroidManifest.xml 还可以用于声明应用程序的其他配置项,例如:
版本号和版本名称的声明
支持的屏幕尺寸和分辨率
应用程序主题和样式
启动模式和任务栈管理
其他元数据信息等
通过标签和属性的使用,你可以在 AndroidManifest.xml 中找到更多相关的配置选项。
网络与服务 && webview
- 声明对象 参数 操作类型
网络和服务 && HttpUrlConnection
网络和服务 && JSON数据解析
网络和服务 && UI线程
网络和服务 && AsyncTask
事件处理的几种方法
Toast提示框
对话框
自定义对话框
网络和服务
意图和广播 && 广播的发送
意图和广播 && 广播接收器
调试之 Log和LogCat的详解
为什么使用Log而不使用System.out
System.out.println()方法来打印日志
这个方法除了使用方便一点之外,其他就一无是处了。
在Eclipse中你只需要输入syso,
然后按下代码提示键,这个方法就会自动出来了
日志打印不可控制、
打印时间无法确定、
不能添加过滤器、
日志没有级别区分……
在LogCat中是可以很轻松地添加过滤器
有两个过滤器
All messages过滤器也就相当于没有过滤器,会把所有的日志都显示出来
com.test.helloworld过滤器是我们运行HelloWorld项目时自动创建的
点击这个过滤器就可以只看到HelloWorld程序中打印的日志
自定义过滤器
onCreate()方法里打印的日志没了,
因为data这个过滤器只会显示Tag名称为data的日志。
你可以尝试在onCreate()方法中把打印日志的语句改成
Log.d(“data”, “onCreate execute”),
然后再次运行程序,你就会在data过滤器下看到这行日志了。
LogCat中的5个级别日志级别控制
调试信息分为五类:
VERBOSE 类型调试信息,verbose啰嗦的意思
DEBUG 类型调试信息, debug调试信息
INFO 类型调试信息, 一般提示性的消息information
WARN 类型调试信息,warning警告类型信息
ERROR 类型调试信息,错误信息
Log.v(String tag, String msg); //VERBOSE
Log.d(String tag, String msg); //DEBUG
Log.i(String tag, String msg); //INFO
Log.w(String tag, String msg); //WARN
Log.e(String tag, String msg); //ERROR
Tag为调试信息标签名称,msg为添加的调试信息
Android Log调试信息的显示
Android Log添加的调试信息主要在logcat中显示,
在安装好Android开发环境的eclipse中DDMS模式和Debug模式下都有Logcat标签窗口,里面会显示所有的调试信息。
具体该调用哪个方法添加什么类型的调试信息?
可根据Logcat提供的过滤器来和信息类型
来决定使用Log的那个方法添加哪类调试信息。
Logcat调试信息显示窗口 右上方有5个图标,
代表 过滤器,可过滤输出相应的调试信息:
V:不过滤输出所有调试信息
包括 VERBOSE、DEBUG、INFO、WARN、ERROR
D:debug过滤器,输出DEBUG、INFO、WARN、ERROR调试信息
I:info过滤器,输出INFO、WARN、ERROR调试信息
W:waring过滤器,输出WARN和ERROR调试信息
E:error过滤器,只输出ERROR调试信息
adb查看Log日志
cmd命令行中使用adb logcat命令查看android系统和应用的log,
dos窗口按ctrl+c中断输出log记录。
logcat日志中的优先级/tag标记:
android输出的每一条日志都有一个标记和优先级与其关联。
优先级是下面的字符,顺序是从低到高:
V — 明细 verbose(最低优先级)
D — 调试 debug
I — 信息 info
W — 警告 warn
E — 错误 error
F — 严重错误 fatal
S — 无记载 silent
- 标记是一个简短的字符串,用于标识原始消息的来源。
– 如下是一个日志输出的消息,优先级是“D”,标记是“PowerManagerService”:
D/PowerManagerService( 305): onSensorChanged: light value: 306.0
–使用logcat命令查看android日志输出:
adb logcat //显示全部日志
adb logcat > c:\test.log //将日志保存到文件test.log
–根据tag标记和级别过滤日志输出:
仅输出标记为“ActivityManager”且优先级大于等于“Info”和标记 为“PowerManagerService”并且优先级大于等于“Debug”的日志:
adb logcat ActivityManager:I PowerManagerService:D *:S
注:*:S用于设置所有标记的日志优先级为S,这样可以确保仅输出符合条件的日志。
adb logcat *:W //显示所有优先级大于等于“warning”的日志
adb logcat -s PowerManagerService //显示PowerManagerService的日志信息
Logcat命令列表:
-d 将日志显示在控制台后退出
-c 清理已存在的日志
-f <filename> 将日志输出到文件
adb logcat -f /sdcard/test.txt
-v <format>设置日志输入格式控制输出字段,默认的是brief格式
brief — 显示优先级/标记和原始进程的PID (默认格式)
process — 仅显示进程PID
tag — 仅显示优先级/标记
thread — 仅显示进程:线程和优先级/标记
raw — 显示原始的日志信息,没有其他的元数据字段
time — 显示日期,调用时间,优先级/标记,PID
long —显示所有的元数据字段并且用空行分隔消息内容
adb logcat -v thread //使用 thread 输出格式
注意-v 选项中只能指定一种格式。
-b <buffer>加载一个可使用的日志缓冲区供查看,默认值是main。
radio — 查看包含在无线/电话相关的缓冲区消息
events — 查看事件相关的消息
main — 查看主缓冲区 (默认缓冲区)
adb logcat -b radio //查看radio缓冲区
ListView 信息展示
动态添加View之addView
启动一个界面以后,
在某一条件下需要再向Activity中添加一个View,
而这个View的位置我们也是事先未知的,
其坐标是某一随机值或者是相对于某一View而进行设置
– 通过addView的方式动态向布局中添加View了。
(ps:addView是ViewGroup中特有的方法,而单一的View是不存在该方法的)
– addView的使用
addView(View child) // child-被添加的View
addView(View child, int index) // index-被添加的View的索引
addView(View child, int width, int height) // width,height被添加的View指定的宽高
addView(View view, ViewGroup.LayoutParams params) // params被添加的View指定的布局参数
addView(View child, int index, LayoutParams params)
– 在LinearLayout中的使用:
使用LinearLayout
因为 线性布局中 更好的理解index这个参数的含义。
- LinearLayout中View的排列是 按照指定的方向 上 线性排列的,
- 子View的索引也是 从零开始按照排列的顺序 依次递增