Android一次本意是“机器人”,谷歌2007年基于linux平台开源手机操作系统的名称。由操作系统,中间件,用户界面和应用软件组成。
安卓开发是基于linux内核的(与硬件打交道的)
Hal层(硬件抽象层):目的是把Android框架和内核分隔
Android Runtime(运行层):每个应用都在自己的进程中运行,每个进程都需要有Android Runtime运行环境,运行环境需要DEX文件,所以需要将java代码编译成DEX字节码运行
Java API FrameWork:(应用层) 开发人员需要掌握的一些api
System APP(安卓系统app)照相机 邮件...
安卓开发四大组件
- 1 activity(活动)
所有程序的根本,所有app应用页面的跳转都是activity中,直观能看到的组件。 - 2 service(服务)
没有界面,运行在后台程序的。service是可以和activity进行交互的。比如QQ音乐后台运行,并没有关掉。比如升级下载在后台下载。 - 3 BroadcastReceiver(广播接收器)
app应用层进行信息传输的,比如qq填写信息微信可以接收到 - 4 Contentprovider(内容提供者)
提供第三方应用数据访问方案
因为Android对数据保护是很严密的,除了sd卡其他数据是不允许直接被进行访问的,所以Contentprovider可以解决这个麻烦
Android平台优势
开放性:所有源代码是开源的
丰富的硬件:因为有很多厂商都在用Android
方便开发:成本很低,直接能安装在手机上
二,安卓开发环境搭建
安卓开发工具
-
1 android studio
是谷歌开发的集成工具,是基于intellig IDEA类似于eclipse
下载地址 -
2 eclipse
早期开发工具,目前已经被淘汰了 -
android SDK(software development kit)软件开发工具包
采用的是java语言,所以需要先安装jdk5以上版本
首先我们电脑环境变量先配置好java
studio安装包
SDK
第一步选custom 这是自定义设置
image.png
配置sdk环境变量
image.png
然后在系统path变量中新建,配置SDK的platform-tools和tools目录
三,android UI基础
android UI
- UI
user interface(用户界面)简称UI,是系统和用户之间进行交互的媒介。软件设计可以分为编码设计和UI设计 - android UI
android提供了很多预置的UI组件,例如结构化布局和UI控件
布局
layout布局,定义应用中的页面结构,布局中所有元素均使用view和viewgroup对象的层次进行构建,view绘制用户查看并进行交互的内容,而viewgroup是容器
布局
view称为微件:如button按钮和textview文本视图
viewgroup为布局:linerlayout和constraintlayout
布局的两种构建方法,一种可以使用xml标签的形式,另一种可以使用代码new对象运行
xml 代码
编写xml布局是写在这里的
xml
加载xml资源
加载资源显示
属性
每个view对象和viewgroup对象都有自己xml属性,其中有一些是特有的,还有共有的。
属性
- id属性
任何view对象均有与之关系的整型id,用于结构树中唯一标识的编号,编译应用后会以整形的形式用此id
xml内部标记id语法:android:id="@+id/命名的id值";
@+id和@id区别
@+id是在R.java文件中新增一个id名称,如果存在相同名字id会替换掉
@id是直接饮用在R.java存在的id资源,如果不存在编译报错
id字符串名称同一布局必须唯一。
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello 啊啊啊啊啊啊"
android:textsize="25sp"/>
//根据查找R.java中的id去展示这个视图
TextView tv = (TextView)findViewById(R.id.tv);
布局参数
主要是给我们设定在布局中位置和大小
layout_ *** 的布局属性
<TextView
android:layout_width="100dp"
android:layout_height="200dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="hello "/>
image.png
在安卓开发不建议使用px来指定布局的宽度和高度,一般使用相对测量的单位,如db(与密度无关的像素单位),wrap-content(视图设置大小的 文字大尺寸大),match-content(视图采用父视图组件所允许的最大尺寸 ,比如文本外嵌套了一个视图容器,只能撑满父级容器)
布局位置
比如视图在视图容器中会有一个坐标点和宽高
坐标点是通过getLeft()和getTop()方法来获取对于父视图左边距和上边距
宽高是通过getWidth()和getHeight()获取视图的尺寸
px和pd区别
px就是像素点,比如手机是19201080,那么宽高像素点就是19201080,
dp是与像素密度有关,每英寸包含的像素数
比如屏幕物理尺寸是1.5英寸x2英寸,屏幕分辨率为240*320,则我们可以计算出横向的每英寸像素点为240/1.5=60dpi.
内边距和外边距
内边距是视图和容器的距离,外边距是容器和容器间的距离
边距
常用布局
- 1 LinearLayout线性布局
是一个视图容器,用于里面子视图在单个(垂直、水平)方向对齐
android:orientation="horizontal"属性为水平对齐
水平
android:orientation="vertical"为垂直对齐
android:layout_weight分配子视图所占空间比重.
image.png -
2 RelativeLayout 相对布局
子视图通过相应的布局属性,设定另一个兄弟/父容器的相对位置
相对兄弟
相对父元素
对齐方式
属性名称 | 涵义 |
---|---|
android:layout_centerInParent="true" | 居中对齐 |
android:layout_centerVertical="true" | 垂直居中对齐 |
android:layout_centerHorizontal="true" | 水平居中对齐 |
-
3 FrameLayout 帧布局(应用很少)
最简单的布局
特点
没有任何布局方式
添加控件的时候默认在左上角
大小控件由最大的控件决定
如果控件一样大只能看见最上面的 -
4 GridLayout 网格布局
类似于手机拨号键盘的布局
属性名称 | 涵义 |
---|---|
android:columnCount | 列数 |
android:rowCount | 行数 |
android:layout_columnSpan | 横跨的列数 |
android:layout_rowSpan | 横跨的行数 |
填充满用android:layout_gravity="fill"
四,常用组件
TextView
文本框,主要用于显示文本的组件
文本字体尺寸单位sp
文本常用属性
属性名称 | 作用 |
---|---|
id | 根据id获取该对象,然后可以通过java代码中findViewById()方法获取该对象,然后进行设置 |
layout_width | 组件的宽度 |
layout_height | 组件的高度 |
gravity | 设置控件中内容对齐方式 |
text | 设置显示文本内容,一般把字符串写在String.xml文件中,通过@String/xxx获取 |
textColor | 字体颜色,通过colors.xml文件来引用 |
textStyle | 设置字体风格,加粗,倾斜 |
background | 背景颜色 |
autoLink | 识别链接类型(web email all) |
- 文本设置边框
编写一个shapeDrawable的资源文件,然后将TextView的background属性设置为drawable资源即可
android shape的使用
在安卓开发中我们可以使用android shape定义各种各样的形状还有图片资源,相对于传统图片来说,使用shape可以减少资源占用,减少安装包大小,适配各种手机
在drawable中,创建一个xml文件
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<!--定义圆角-->
<corners android:radius="8dp"/>
<!--指定内部的填充色-->
<solid android:color="@color/red"/>
<!--矩形的边框线-->
<stroke android:color="@color/white" android:width="1dp"/>
</shape>
在xml中,用background调用就行了
<Button
android:id="@+id/btn_startaduio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/start"
android:enabled="false"
android:text="开始"
android:textColor="#ffffff" />
定义圆角矩形
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
>
<!-- 设置透明背景色 -->
<solid android:color="#87CEEB" />
<!-- 设置一个黑色边框 -->
<stroke
android:width="2px"
android:color="#000000" />
<!-- 设置四个圆角的半径 -->
<corners
android:bottomLeftRadius="10px"
android:bottomRightRadius="10px"
android:topLeftRadius="10px"
android:topRightRadius="10px" />
<!-- 设置一下边距,让空间大一点 -->
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
带图片(drawableXxx)的TextView
属性名 | 作用 |
---|---|
android:drawableLeft | 文本左边设置图片 |
android:drawableRight | 文本右边设置图片 |
android:drawableBottom | 文本下边设置图片 |
android:drawableTop | 文本上边设置图片 |
EditText输入框
继承TextView
比如用户名密码的输入框
属姓名 | 说明 |
---|---|
android:hint | 默认提示文本 |
android:textColorHint | 默认提示文本的颜色 |
android:selectAllOnFocus | 布尔值。点击输入框获得焦点后,获取到输入框中所有的文本内容 |
android:inputType | 对输入的数据进行限制 |
android:minLines | 设置最小行数 |
android:maxLines | 设置最大行数 PS:当输入内容超过maxline,文字会自动向上滚动!! |
android:singleLine | 只允许单行输入,而且不会滚动 |
android:textScaleX | 设置字与字的水平间隔 |
android:textScaleY | 设置字与字的垂直间隔 |
android:capitalize | 设置字与字的垂直间隔 |
sentences: | 仅第一个字母大写 ;words:每一个单词首字母大小,用空格区分单词;characters:每一个英文字母都大写 |
文本类型
android:inputType="none"
android:inputType="text"
android:inputType="textCapCharacters"
android:inputType="textCapWords"
android:inputType="textCapSentences"
android:inputType="textAutoCorrect"
android:inputType="textAutoComplete"
android:inputType="textMultiLine"
android:inputType="textImeMultiLine"
android:inputType="textNoSuggestions"
android:inputType="textUri"
android:inputType="textEmailAddress"
android:inputType="textEmailSubject"
android:inputType="textShortMessage"
android:inputType="textLongMessage"
android:inputType="textPersonName"
android:inputType="textPostalAddress"
android:inputType="textPassword"
android:inputType="textVisiblePassword"
android:inputType="textWebEditText"
android:inputType="textFilter"
android:inputType="textPhonetic"
数值类型
android:inputType="number"
android:inputType="numberSigned"
android:inputType="numberDecimal"
android:inputType="phone"//拨号键盘
android:inputType="datetime"
android:inputType="date"//日期键盘
android:inputType="time"//时间键盘
设置EditText获得焦点,同时弹出小键盘
edit.requestFocus(); //请求获取焦点
edit.clearFocus(); //清除焦点
定位光标所在位置
e.requestFocus();//获取焦点
e.setSelection(2);//定位光标在第二个字符后
那么对于高版本的安卓获取焦点需要手动弹出键盘
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
对于高版本
Button(按钮)
也是继承TextView
StateListDrawable 是Drawable资源的一种,可以根据不同的状态,设置不同的图片效果,关
键节点 < selector > ,我们只需要将Button的 background 属性设置为该drawable资源即可轻
松实现,按下 按钮时不同的按钮颜色或背景
属性名 | 说明 |
---|---|
drawable | 引用的Drawable位图,我们可以把他放到最前面,就表示组件的正常状态~ |
state_focused | 是否获得焦点 |
state_window_focused | 是否获得窗口焦点 |
state_enabled | 控件是否可用 |
state_checkable | 控件可否被勾选 |
state_checked | 控件是否被勾选 |
state_selected | 控件是否被选择,针对有滚轮的情况 |
state_pressed | 控件是否被按下 |
state_active | 控件是否处于活动状态 |
state_single | 控件包含多个子控件时,确定是否只显示一个子控件 |
state_first | 控件包含多个子控件时,确定第一个子控件是否处于显示状态 |
state_middle | 控件包含多个子控件时,确定中间一个子控件是否处于显示状态 |
state_last | 控件包含多个子控件时,确定最后一个子控件是否处于显示状态 |
- btn_bg1.xml
?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/color1" android:state_pressed="true"
/>
<item android:drawable="@color/color4" android:state_enabled="false"
/>
<item android:drawable="@color/color3" />
</selector>
1
- layout_btn.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"
android:paddingTop="50dp">
<Button
android:id="@+id/btnOne"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="@drawable/btn_bg1"
android:text="按钮"
android:textColor="#ffffff"
android:textSize="20sp"
android:textStyle="bold" />
<Button
android:id="@+id/btnTwo"
android:layout_width="match_parent"
android:layout_height="64dp"
android:text="按钮不可用"
android:textColor="#000000"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
- MainActivity.java
ublic class MainActivity extends Activity {
private Button btnOne,btnTwo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnOne = (Button) findViewById(R.id.btnOne);
btnTwo = (Button) findViewById(R.id.btnTwo);
btnTwo.setOnClickListener(new OnClickListener() { //按钮绑定点击
事件
@Override
public void onClick(View v) {
if(btnTwo.getText().toString().equals("按钮不可用")){
btnOne.setEnabled(false);
btnTwo.setText("按钮可用");
}else{
btnOne.setEnabled(true);
btnTwo.setText("按钮不可用");
}
}
});
}
}
ImageView(图像视图)
就是用来显示图像的view
ImageView有两个设置图片的属性 1是src ,2是background
src按照图片大小直接填充,不会拉伸
background根据ImageView给定的宽度进行拉伸
- android:scale
android:scaleType用于设置显示的图片如何缩放或者移动以适应ImageView的大小 Java代
码中可以通过imageView.setScaleType(ImageView.ScaleType.CENTER);来设置~ 可选
值如下:
fitXY:对图像的横向与纵向进行独立缩放,使得该图片完全适应ImageView,但是图片的横纵比
可能会发生改变
fitStart:保持纵横比缩放图片,知道较长的边与Image的编程相等,缩放完成后将图片放在
ImageView的左上角
fitCenter:同上,缩放后放于中间;
fitEnd:同上,缩放后放于右下角;
center:保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size,
超过部分裁剪处理。
centerCrop:保持横纵比缩放图片,知道完全覆盖ImageView,可能会出现图片的显示不完全
centerInside:保持横纵比缩放图片,直到ImageView能够完全地显示图片
matrix:默认值,不改变原图的大小,从ImageView的左上角开始绘制原图, 原图超过
ImageView的部分作裁剪处理
-
fitEnd , fitStart , fitCenter
-
centerCrop 与 centerInside
centerCrop:按横纵比缩放,直接完全覆盖整个ImageView
centerInside:按横纵比缩放,使得ImageView能够完全显示这个图片 -
fitXY
不按比例缩放图片,目标是把图片塞满整个View -
matrix
从ImageView的左上角开始绘制原图,原图超过ImageView的部分作裁剪处理 -
center
保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size,超过部分裁剪处理。
RadioButton(单选按钮)和checkBox(复选框)
RadioButton必须是放在RadioGroup按钮组中,另外我们可以为RadioGroup设置orientation属性设置内部单选按钮的排列方式.
例图
image.png
开关按钮
- 1 ToggleVutton按钮
属姓名 | 说明 |
---|---|
android:disabledAlpha | 设置按钮在禁用时的透明度 |
android:textOff | 按钮没有被选中时显示的文字 |
android:textOn | 按钮被选中时显示的文字 |
- 2 switch
属姓名 | 说明 |
---|---|
android:showText | 设置ON/off是否显示文字 |
android:textOff | 按钮没有被选中时显示的文字 |
android:textOn | 按钮被选中时显示的文字 |
android:switchMinWidth | 设置开关最小宽度 |
android:switchTextAppearance | 设置文字外观 |
android:switchPadding | 设置滑块内文字间隔 |
ProgressBar进度条
常见属性
android:max:进度条的最大值
android:progress:进度条已完成进度值
android:progressDrawable:设置轨道对应的Drawable对象
android:indeterminate:如果设置成true,则进度条不精确显示进度
android:indeterminateDrawable:设置不显示进度的进度条的Drawable对象
android:indeterminateDuration:设置不精确显示进度的持续时间
android:secondaryProgress:二级进度条,类似于视频播放的一条是当前播放进度,一条是缓冲进度,前者通过progress属性进行设置!
对应java中可以调用
getMax():返回这个进度条的范围的上限
getProgress():返回进度
getSecondaryProgress():返回次要进度
incrementProgressBy(int diff):指定增加的进度
isIndeterminate():指示进度条是否在不确定模式下
setIndeterminate(boolean indeterminate):设置不确定模式下
SeekBar拖动条
android:max="100" //滑动条的最大值
android:progress="60" //滑动条的当前值
android:secondaryProgress="70" //二级滑动条的进度
android:thumb = "@mipmap/sb_icon" //滑块的drawable
事件
nProgressChanged:进度发生改变时会触发
onStartTrackingTouch:按住SeekBar时会触发
onStopTrackingTouch:放开SeekBar时触发
ScrollView滚动条
如长文章的滚动条
我们可以直接利用ScrollView给我们提供的:fullScroll()方法:
scrollView.fullScroll(ScrollView.FOCUS_DOWN);滚动到底部
scrollView.fullScroll(ScrollView.FOCUS_UP);滚动到顶部
隐藏滑块:
android:scrollbars="none"
设置滚动速度:
继承ScrollView,然后重写一个 public void fling (int velocityY)的方法:
@Override
public void fling(int velocityY) {
super.fling(velocityY / 2); //速度变为原来的一半
}
tips: ScrollView控件中只能包含一个View或一个ViewGroup
Date Time组件
- 1 TextClock(文本时钟)
ttribute Name Related Method Description
android:format12Hour setFormat12Hour(CharSequence) 设置12时制的格式
android:format24Hour setFormat24Hour(CharSequence) 设置24时制的格式
android:timeZone setTimeZone(String) 设置时区
- 2 analogClock 模拟时钟
android:dial //表背景图片
android:hand_hour //表时针图片
android:hand_minute //分时针图片
-
3 Chronometer计时器
-
4 Datepicker 日期选择器
android:calendarTextColor : 日历列表的文本的颜色
android:calendarViewShown:是否显示日历视图
android:datePickerMode:组件外观,可选值:spinner,calendar 前者效果如下,默认
效果是后者
android:dayOfWeekBackground:顶部星期几的背景颜色
android:dayOfWeekTextAppearance:顶部星期几的文字颜色
android:endYear:去年(内容)比如2010
android:firstDayOfWeek:设置日历列表以星期几开头
android:headerBackground:整个头部的背景颜色
android:headerDayOfMonthTextAppearance:头部日期字体的颜色
android:headerMonthTextAppearance:头部月份的字体颜色
android:headerYearTextAppearance:头部年的字体颜色
android:maxDate:最大日期显示在这个日历视图mm / dd / yyyy格式
android:minDate:最小日期显示在这个日历视图mm / dd / yyyy格式
android:spinnersShown:是否显示spinner
android:startYear:设置第一年(内容),比如19940年
android:yearListItemTextAppearance:列表的文本出现在列表中。
android:yearListSelectorColor:年列表选择的颜色
五,Adapter 适配器基础
MVC理解
MVCmodel :数据源
view:显示视图控件 --AdapteView
Controller:控制器 model和view之间的纽带 --adapter
AdapteView常见适配器有:ListView,GridView,Spinner,recycleView
数据是通过控制器绑定到view上面的
ListView控件
BaseAdapter最基本的几个方法:
1. getCount 填充的数据集数
2. getItem 数据集中指定索引对应的数据项
3. getItemId 指定行所对应的ID
4. getView 每个Item所显示的类容
image.png
ListView实现多种布局风格
重写getItemViewType()方法对应View是哪个类别,以getViewTypeCount()方法iew返回 总共多少个类别!然后再getView那里调用getItemViewType获得对应类别,再加载对应的View!
GridView网格视图
网格视图android:columnWidth:设置列的宽度
android:gravity:组件对其方式
android:horizontalSpacing:水平方向每个单元格的间距
android:verticalSpacing:垂直方向每个单元格的间距
android:numColumns:设置列数
android:stretchMode:设置拉伸模式,可选值如下: none:不拉伸;spacingWidth:拉伸元素
间的间隔空隙 columnWidth:仅仅拉伸表格元素自身 spacingWidthUniform:既拉元素间距又拉伸
他们之间的间隔空袭
GridViewActivity.java
package com.ttit.helloworld;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.ttit.helloworld.adapter.GridViewAdpater;
import com.ttit.helloworld.entity.Icon;
import java.util.ArrayList;
import java.util.List;
public class GridViewActivity extends AppCompatActivity {
private Context mContext;
private GridView grid_photo;
private GridViewAdpater mAdapter = null;
private List<Icon> mData = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gridview_layout);
mContext = this;
//视图层V
grid_photo = (GridView) findViewById(R.id.gridView);
//数据源M
mData = new ArrayList();
mData.add(new Icon(R.mipmap.iv_icon_1, "图标1"));
mData.add(new Icon(R.mipmap.iv_icon_2, "图标2"));
mData.add(new Icon(R.mipmap.iv_icon_3, "图标3"));
mData.add(new Icon(R.mipmap.iv_icon_4, "图标4"));
mData.add(new Icon(R.mipmap.iv_icon_5, "图标5"));
mData.add(new Icon(R.mipmap.iv_icon_6, "图标6"));
mData.add(new Icon(R.mipmap.iv_icon_7, "图标7"));
//控制层C
mAdapter = new GridViewAdpater(mData, mContext);
grid_photo.setAdapter(mAdapter);
//点击事件
grid_photo.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
Toast.makeText(mContext, "你点击了~" + position + "~项",
Toast.LENGTH_SHORT).show();
}
});
}
}
Spinner列表选项框
image.pngandroid:dropDownHorizontalOffset:设置列表框的水平偏移距离
android:dropDownVerticalOffset:设置列表框的水平竖直距离
android:dropDownSelector:列表框被选中时的背景
android:dropDownWidth:设置下拉列表框的宽度
android:gravity:设置里面组件的对其方式
android:popupBackground:设置列表框的背景
android:prompt:设置对话框模式的列表框的提示信息(标题),只能够引用string.xml 中的资源
id,而不能直接写字符串
android:spinnerMode:列表框的模式,有两个可选值: dialog:对话框风格的窗口 dropdown:
下拉菜单风格的窗口(默认)
可选属性:android:entries:使用数组资源设置下拉列表框的列表项目
ExpandableListView 可折叠列表
可折叠列表有一点要注意的是,重写isChildSelectable()方法需要返回true,不然不会触发子Item的点击事件
实现ExpandableAdapter的三种方式
1. 扩展BaseExpandableListAdpter实现ExpandableAdapter。
2. 使用SimpleExpandableListAdpater将两个List集合包装成ExpandableAdapter
3. 使用simpleCursorTreeAdapter将Cursor中的数据包装成SimpleCuroTreeAdapter 本节示
例使用的是第一个,扩展BaseExpandableListAdpter,我们需要重写该类中的相关方法, 下面我们
通过一个代码示例来体验下!
Toast 吐司
安卓用于提示信息的一个组件
AlertDialog对话框
Step 1:创建AlertDialog.Builder对象;
Step 2:调用setIcon()设置图标,setTitle()或setCustomTitle()设置标题;
Step 3:设置对话框的内容:setMessage()还有其他方法来指定显示的内容;
Step 4:调用setPositive/Negative/NeutralButton()设置:确定,取消,中立按钮;
Step 5:调用create()方法创建这个对象,再调用show()方法将对话框显示出来;
六,Android事件分发机制
- 1 被分发的对象
就是用户触发屏幕而产生的点击事件.
事件 | 触发场景 | 单次事件流中触发的次数 |
---|---|---|
MotionEvent.Action_DOWN | 在屏幕按下时 | 1次 |
MotionEvent.Action_MOVE | 在屏幕滑动时 | 0次或多次 |
MotionEvent.Action_UP | 在屏幕抬起时 | 0次或多次 |
MotionEvent.Action_CANCLE | 滑动超出控件边界 | 0次或多次 |
PopupWindow悬浮框
与AlertDialog区别:
本质区别为:AlertDialog是非阻塞式对话框:AlertDialog弹出时,后台还可以做事情;而
PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一
直等待,只有当我们调用了dismiss方法的后,PopupWindow退出,程序才会向下执行。这两种区别的
表现是:AlertDialog弹出时,背景是黑色的,但是当我们点击背景,AlertDialog会消失,证明程序
不仅响应AlertDialog的操作,还响应其他操作,其他程序没有被阻塞,这说明了AlertDialog是非阻
塞式对话框;PopupWindow弹出时,背景没有什么变化,但是当我们点击背景的时候,程序没有响应,
只允许我们操作PopupWindow,其他操作被阻塞。
七,四大组件
1.Activity
用于显示用户界面,用户通过Activity交互完成相关操作
1个app允许有多个Activity
继承Activity和AppCompatActivity区别
AppCompatActivity兼容了很多低版本的东西
Activity创建流程
- 1自定义 Activity类名,继承Activity或其他子类
Class MyActivity extends Activity{} - 2 重写onCreate方法,在该方法中调用setContentView()设置要显示的视图
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载显示的页面布局
setContentView(R.layout.index_layout);
}
- 3 在androidMainfest.xml对Activity进行配置
<activity
//进行配置
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- 4 启动Activity调用startActivity(Intent)
比如单击按钮跳转到第二个页面
两种启动
1显示启动
Intent in = new Intent (firstActivity.this,secondActivity.class);
startActivity(in);//first跳转到second页面
2 隐式启动
Intent in = new Intent ("传入");<action android:name="android.intent.action.MAIN" />
startActivity(in);
Activity生命周期
image.pngActivity组件间通信 Intent
每个应用是由多个activity组成的,每个页面之间需要通信
Intent in = new Intent(FirstActivity.this, ThirdActivity.class);
//1.传单个数据
in.putExtra("test","TTIT");
in.putExtra("number",100);
//2.传多个数据
Bundle b = new Bundle();
b.putInt("number", 100);
b.putString("test", "TTIT");
in.putExtras(b);
startActivity(in);
获取数据
获取单个数据 获取多个数据
如从第三个页面返回到第一个页面时,进行返回数据操作
第二个页面给第一个页面返回和接收数据
startActivityForResult(in, 1001);
FirstActivity接受ThirdActivity返回的数据
@Override
protected void onActivityResult(int requestCode, int
resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e("tag", "requestCode =" + requestCode);
Log.e("tag", "resultCode =" + resultCode);
Log.e("tag", "data =" + data.getStringExtra("back"));
}
3.ThirdActivity设置返回的数据
Intent backIn = new Intent();
backIn.putExtra("back", "abcdef");
setResult(1002, backIn);
Activity启动模式
standard标准模式 每一次点击都会创建一个activity实例,放在栈内存中,如果你点击3次,退出的话也要点击3次
image.pngsingleTop模式
如果栈顶activity为我们要新建的activity,那么就不会重新创建activity
image.png
singleTask
image.pngsingleInstance模式
image.png2.Service(服务)组件
线程
- 程序
为了完成特定任务,用某种语言完成一组指令 - 进程
运行中的程序,操作系统会为每个进程分配一个内存空间。程序一次动态执行,经历了代码的加载,执行,执行完毕的过程 - 线程
比进程更小的执行单元,线程需要放到一个进程中才能执行,线程由程序负责管理。进程直接由系统直接调度
多线程
就是一个进程并行了多个线程,将cpu时间片按照调度算法分配给各个线程,实际是分时管理的,只是切换时间很短,用户感受不到而已
image.png
创建线程的方式 (3种)
1 继承thread类
public class MyThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
//super.run();
doSomething();
}
private void doSomething() {
// TODO Auto-generated method stub
System.out.println("我是一个线程中的方法");
}
}
==================================================================
public class NewThread {
public static void main(String[] args) {
MyThread myThread=new MyThread();
myThread.start();//开启一个线程方法
//以下的方法可与上边的线程并发执行
do();
}
private static void doSomething() {
// TODO Auto-generated method stub
}
}
- 实现Runnable接口
public class RunnableThread implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
doSomeThing();
}
private void doSomeThing() {
// TODO Auto-generated method stub
System.out.println("我是一个线程方法");
}
}
===================================================================
===============
public class NewThread {
public static void main(String[] args) {
Runnable runnable=new RunnableThread();
Thread thread=new Thread(runnable);
thread.start();//开启一个线程方法
//以下的方法可与上边的线程并发执行
do();
}
private static void doSomething() {
// TODO Auto-generated method stub
}
}
- 实现Callable接口和Future创建线程
public class CallableThread implements Callable<String>{
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
doSomeThing();
return "需要返回的值";
}
private void doSomeThing() {
// TODO Auto-generated method stub
System.out.println("我是线程中的方法");
}
}
===================================================================
===============
public class NewThread {
public static void main(String[] args) {
Callable<String> callable=new CallableThread();
FutureTask<String> futureTask=new FutureTask<String>
(callable);
Thread thread=new Thread(futureTask);
thread.start();//开启一个线程方法
//以下的方法可与上边的线程并发执行
doSomething();
try {
futureTask.get();//获取线程返回值
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void doSomething() {
// TODO Auto-generated method stub
}
}
service生命周期
service生命周期生命周期函数解析:
- 1 onCreate():当Service第一次被创建后立即回调该方法,该方法在整个生命周期 中只会调用一
次! - 2 onDestory():当Service被关闭时会回调该方法,该方法只会回调一次!
- 3 onStartCommand(intent,flag,startId):早期版本是onStart(intent,startId), 当客
户端调用startService(Intent)方法时会回调,可多次调用StartService方法, 但不会再创建新
的Service对象,而是继续复用前面产生的Service对象,但会继续回调 onStartCommand()方法!
IBinder onOnbind(intent):该方法是Service都必须实现的方法,该方法会返回一个 IBinder
对象,app通过该对象与Service组件进行通信!
*4 onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!
BroadcastReceiver广播接收器组件
为了方便Android系统各个应用及程序内部进行通信,为此Android系统有一套完整的api,允许程序接收和发送广播
- 1 标准广播
是一种完全异步执行的广播,在广播发出之后,所有的广播接收器会在同一时间接收到这条广
播,广播无法被截断.
发送方式:
Intent intent=new Intent("com.example.dimple.BROADCAST_TEST");
sendBroadcast(intent);
- 2 有序广播
是一种同步执行的广播,在广播发出之后,优先级高的广播接收器可以优先接收到这条广播,
并可以在优先级较低的广播接收器之前截断停止发送这条广播。
发送方式:
Intent intent=new Intent("com.example.dimple.BROADCAST_TEST");
sendOrderBroadcast(intent,null);//第二个参数是与权限相关的字符串。
注册广播
在Android的广播接收机制中,如果需要接收广播,就需要创建广播接收器。而创建广播接收器的
方法就是新建一个类(可以是单独新建类,也可以是内部类(public)) 继承自
BroadcastReceiver
class myBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//不要在广播里添加过多逻辑或者进行任何耗时操作,因为在广播中是不允许开辟
线程的, 当onReceiver( )方法运行较长时间(超过10秒)还没有结束的话,那么程序会报错
(ANR), 广播更多的时候扮演的是一个打开其他组件的角色,比如启动Service,Notification
提示, Activity等!
}
}
注册有两种方式,静态和动态,区别是
动态注册的广播接收器可以自由的控制注册和取消,有很大的灵活性。但是只能在程序启动之后才能收到广播,此外,不知道你注意到了没,广播接收器的注销是在onDestroy()方法中的。所以广播接收器的生命周期是和当前活动的生命周期一样。
静态注册的广播不受程序是否启动的约束,当应用程序关闭之后,还是可以接收到广播。
- 动态注册
所谓动态注册是指在代码中注册。步骤如下 :
- 实例化自定义的广播接收器。
- 创建IntentFilter实例。
- 调用IntentFilter实例的addAction()方法添加监听的广播类型。
- 最后调用Context的registerReceiver(BroadcastReceiver,IntentFilter)动
态的注册广播。
PS:这里提醒一点,如果需要接收系统的广播(比如电量变化,网络变化等等),别忘记在
AndroidManifest配置文件中加上权限。
另外,动态注册的广播在活动结束的时候需要取消注册:
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myBroadcastReceiver);
}
- 静态注册
<receiver
android:name="com.ttit.core.broadcastreceiver.MyBRReceiver2">
<intent-filter>
<action
android:name="com.example.broadcasttest.MY_BROADCAST" />
</intent-filter>
</receiver>
ContentProvider 内容提供者组件 (操作数据库)
我们想在自己的应用中访问别的应用,或者说一些ContentProvider暴露给我们的一些数据, 比如
手机联系人,短信等!我们想对这些数据进行读取或者修改,这就需要用到ContentProvider了!我们自己的应用,想把自己的一些数据暴露出来,给其他的应用进行读取或操作,我们也可以用到ContentProvider,另外我们可以选择要暴露的数据,就避免了我们隐私数据的的泄露!
uri
image.png
主要分三个部分:scheme, authority and path。scheme表示上图中的content://,
authority表示B部分,path表示C和D部分。
A部分:表示是一个Android内容URI,说明由ContentProvider控制数据,该部分是固定形式,不可
更改的。
B部分:是URI的授权部分,是唯一标识符,用来定位ContentProvider。格式一般是自定义
ContentProvider类的完全限定名称,注册时需要用到,如:
com.example.transportationprovider
C部分和D部分:是每个ContentProvider内部的路径部分,C和D部分称为路径片段,C部分指向一个对
象集合,一般用表的名字,如:/trains表示一个笔记集合;D部分指向特定的记录,
如:/trains/122表示id为122的单条记录,如果没有指定D部分,则返回全部记录。
八,数据存储
SharedPreferences
当我们的应用想要保存用户的一些偏好参数,比如是否自动登陆,是否记住账号密码,是否在Wifi下才能 联网等相关信息,如果使用数据库的话,显得有点大材小用了!我们把上面这些配置信息称为用户的偏好 设置,就是用户偏好的设置,而这些配置信息通常是保存在特定的文件中!比如windows使用ini文件, 而J2SE中使用properties属性文件与xml文件来保存软件的配置信息;而在Android中我们通常使用 一个轻量级的存储类——SharedPreferences来保存用户偏好的参数!SharedPreferences也是使用xml文件, 然后类似于Map集合,使用键-值的形式来存储数据;我们只需要调用SharedPreferences的getXxx(name), 就可以根据键获得对应的值!使用起来很方便
数据库SQLlite
①SQLite是一个轻量级的关系型数据库,运算速度快,占用资源少,很适合在移动设备上使用, 不
仅支持标准SQL语法,还遵循ACID(数据库事务)原则,无需账号,使用起来非常方便!
②前面我们学习了使用文件与SharedPreference来保存数据,但是在很多情况下, 文件并不一定
是有效的,如多线程并发访问是相关的;app要处理可能变化的复杂数据结构等等! 比如银行的存
钱与取钱!使用前两者就会显得很无力或者繁琐,数据库的出现可以解决这种问题, 而Android又
给我们提供了这样一个轻量级的SQLite,为何不用?
③SQLite支持五种数据类型:NULL,INTEGER,REAL(浮点数),TEXT(字符串文本)和BLOB(二进制
对象) 虽然只有五种,但是对于varchar,char等其他数据类型都是可以保存的;因为SQLite有个
最大的特点: 你可以各种数据类型的数据保存到任何字段中而不用关心字段声明的数据类型是什么,
比如你 可以在Integer类型的字段中存放字符串,当然除了声明为主键INTEGER PRIMARY KEY
的字段只能够存储64位整数! 另外, SQLite 在解析CREATE TABLE 语句时, 会忽略
CREATE TABLE 语句中跟在字段名后面的数据类型信息如下面语句会忽略 name字段的类型信息:
CREATE TABLE person (personid integer primary key autoincrement, name
varchar(20))
小结下特点:
SQlite通过文件来保存数据库,一个文件就是一个数据库,数据库中又包含多个表格,表格里又有
多条记录,每个记录由多个字段构成,每个字段有对应的值,每个值我们可以指定类型,也可以不
指定类型(主键除外)
- 相关的类
-SQLiteOpenHelper:抽象类,我们通过继承该类,然后重写数据库创建以及更新的方法, 我们
还可以通过该类的对象获得数据库实例,或者关闭数据库!
-SQLiteDatabase:数据库访问类:我们可以通过该类的对象来对数据库做一些增删改查的操作
-Cursor:游标,有点类似于JDBC里的resultset,结果集!可以简单理解为指向数据库中某 一
个记录的指针!
public class MyDBOpenHelper extends SQLiteOpenHelper {
public MyDBOpenHelper(Context context, String name, CursorFactory
factory,
int version) {super(context, "my.db", null, 1); }
@Override
//数据库第一次创建时被调用
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE person(personid INTEGER PRIMARY KEY
AUTOINCREMENT,name VARCHAR(20))");
}
//软件版本号发生改变时调用
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int
newVersion) {
db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");
}
}
9 HTTP
客户端和web服务器通讯的一种格式
image.png
常见请求参数有
Get:请求获取Request-URI所标识的资源
POST:在Request-URI所标识的资源后附加新的数据
HEAD 请求获取由Request-URI所标识的资源的响应信息报头
PUT:请求服务器存储一个资源,并用Request-URI作为其标识
DELETE:请求服务器删除Request-URI所标识的资源
TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT:保留将来使用
OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项
GET和POST的对比
GET:在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分隔, 但数据容量通常不能超过2K,比如:http://xxx?username=…&pawd=…这种就是GET
POST: 这个则可以在请求的实体内容中向服务器发送数据,传输没有数量限制
另外要说一点,这两个玩意都是发送数据的,只是发送机制不一样,不要相信网上说的 "GET获得服务器数据,POST向服务器发送数据"!!另外GET安全性非常低,Post安全性较高, 但是执行效率却比Post方法好,一般查询的时候我们用GET,数据增删改的时候用POST!
okhtttp
OkHttp是一个高效的HTTP客户端,它有以下默认特性:
1.支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
2.连接池减少请求延时
3.透明的GZIP压缩减少响应数据的大小
4.缓存响应内容,避免一些完全重复的请求
JSON 和XML对比
JSON和XML的数据可读性基本相同;
JSON和XML同样拥有丰富的解析手段
JSON相对于XML来讲,数据的体积小
JSON与JavaScript的交互更加方便
JSON对数据的描述性比XML较差
JSON的速度要远远快于XML
简单点说Json的优点:体积小,节省流量,只是不如XML直观,可读性 稍微差一点而已!
Android提供的JSON解析类
这些API都存在于org.json包下,而我们用到的类有下面这些:
JSONObject: Json对象,可以完成Json字符串与Java对象的相互转换
JSONArray: Json数组,可以完成Json字符串与Java集合或对象的相互转换
JSONStringer: Json文本构建类,这个类可以帮助快速和便捷的创建JSON text, 每个
JSONStringer实体只能对应创建一个JSON text
JSONTokener:Json解析类
JSONException:Json异常
十,WebView
Android内置了一个webkit内核的高性能浏览器,webview就是把webkit内核封装 ,可以镶嵌在页面上的浏览器控件
Drawable资源
Drawable分为两种:
一种是我们普通的图片资源,在Android Studio中我们一般放到res/mipmap目录下; 另一种是
我们编写的XML形式的Drawable资源,我们一般把他们放到res/drawable目录下,比如最常见
的按钮点击背景切换的Selctor.
在XML我们直接通过@mipmap或者@drawable设置Drawable即可 比如:
android:background = "@mipmap/iv_icon_zhu" /
"@drawable/btn_back_selctor" 而在Java代码中我们可以通过Resource的
getDrawable(R.mipmap.xxx)可以获得drawable资源 如果是为某个控件设置背景,比如
ImageView,我们可以直接调用控件.getDrawale()同样 可以获得drawable对象!
Android中drawable中的资源名称有约束,必须是:[a-z0-9_.](即:只能是字母数字及
和.), 而且不能以数字开头,否则编译会报错: Invalid file name: must contain
only [a-z0-9.]! 小写啊!!!!小写!!!小写!
- ShapeDrawable
形状的Drawable咯,定义基本的几何图形,如(矩形,圆形,线条等),根元素是<shape../> 节点
比较多,相关的节点如下:
① <shape>:
~ visible:设置是否可见
~ shape:形状,可选:rectangle(矩形,包括正方形),oval(椭圆,包括圆),line(线
段),ring(环形)
~ innerRadiusRatio:当shape为ring才有效,表示环内半径所占半径的比率,如果设置了
innerRadius, 他会被忽略
~ innerRadius:当shape为ring才有效,表示环的内半径的尺寸
~ thicknessRatio:当shape为ring才有效,表环厚度占半径的比率
~ thickness:当shape为ring才有效,表示环的厚度,即外半径与内半径的差
~ useLevel:当shape为ring才有效,表示是否允许根据level来显示环的一部分
②<size>:
~ width:图形形状宽度
~ height:图形形状高度
③<gradient>:后面GradientDrawable再讲~
④<solid>
~ color:背景填充色,设置solid后会覆盖gradient设置的所有效果!!!!!!
⑤<stroke>
~ width:边框的宽度
~ color:边框的颜色
~ dashWidth:边框虚线段的长度
~ dashGap:边框的虚线段的间距
⑥<conner>
~ radius:圆角半径,适用于上下左右四个角
~ topLeftRadius,topRightRadius,BottomLeftRadius,tBottomRightRadius: 依次
是左上,右上,左下,右下的圆角值,按自己需要设置!
⑦<padding>
left,top,right,bottm:依次是左上右下方向上的边距!
- GradientDrawable
一个具有渐变区域的Drawable,可以实现线性渐变,发散渐变和平铺渐变效果 核心节点:
<gradient/>,有如下可选属性:
startColor:渐变的起始颜色
centerColor:渐变的中间颜色
endColor:渐变的结束颜色
type:渐变类型,可选(linear,radial,sweep), 线性渐变(可设置渐变角度),发散渐变(中间
向四周发散),平铺渐变
centerX:渐变中间亚瑟的x坐标,取值范围为:0~1
centerY:渐变中间颜色的Y坐标,取值范围为:0~1
angle:只有linear类型的渐变才有效,表示渐变角度,必须为45的倍数哦
gradientRadius:只有radial和sweep类型的渐变才有效,radial必须设置,表示渐变效果的
半径
useLevel:判断是否根据level绘制渐变效果
- BitmapDrawable
对Bitmap的一种封装,可以设置它包装的bitmap在BitmapDrawable区域中的绘制方式,有: 平
铺填充,拉伸填或保持图片原始大小!以<bitmap>为根节点! 可选属性如下:
src:图片资源~
antialias:是否支持抗锯齿
filter:是否支持位图过滤,支持的话可以是图批判显示时比较光滑
dither:是否对位图进行抖动处理
gravity:若位图比容器小,可以设置位图在容器中的相对位置
tileMode:指定图片平铺填充容器的模式,设置这个的话,gravity属性会被忽略,有以下可选值:
disabled(整个图案拉伸平铺),clamp(原图大小), repeat(平铺),mirror(镜像平铺)
- RotateDrawable
用来对Drawable进行旋转,也是通过setLevel来控制旋转的,最大值也是:10000
fromDegrees:起始的角度,,对应最低的level值,默认为0
toDegrees:结束角度,对应最高的level值,默认360
pivotX:设置参照点的x坐标,取值为0~1,默认是50%,即0.5
pivotY:设置参照点的Y坐标,取值为0~1,默认是50%,即0.5 ps:如果出现旋转图片显示不完全的
话可以修改上述两个值解决!
drawable:设置位图资源
visible:设置drawable是否可见
- AnimationDrawable
AnimationDrawable是用来实现Android中帧动画的,就是把一系列的 Drawable,按照一定得
顺序一帧帧地播放;Android中动画比较丰富,有传统补间动画,平移, 缩放等等效果,但是这里我
们仅仅介绍这个AnimationDrawable实现帧动画.
oneshot:设置是否循环播放,false为循环播放!!!
duration:帧间隔时间,通常我们会设置为300毫秒 我们获得AniamtionDrawable实例后,需要
调用它的start()方法播放动画,
- LayerDrawable
层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来绘制他们,索引 值最大的
Drawable会被绘制在最上层!虽然这些Drawable会有交叉或者重叠的区域,但 他们位于不同的
层,所以并不会相互影响,以<layer-list>作为根节点!
drawable:引用的位图资源,如果为空徐璈有一个Drawable类型的子节点
left:层相对于容器的左边距
right:层相对于容器的右边距
top:层相对于容器的上边距
bottom:层相对于容器的下边距
id:层的id
- StateListDrawable
drawable:引用的Drawable位图,我们可以把他放到最前面,就表示组件的正常状态~
state_focused:是否获得焦点
state_window_focused:是否获得窗口焦点
state_enabled:控件是否可用
state_checkable:控件可否被勾选,eg:checkbox
state_checked:控件是否被勾选
state_selected:控件是否被选择,针对有滚轮的情况
state_pressed:控件是否被按下
state_active:控件是否处于活动状态,eg:slidingTab
state_single:控件包含多个子控件时,确定是否只显示一个子控件
state_first:控件包含多个子控件时,确定第一个子控件是否处于显示状态
state_middle:控件包含多个子控件时,确定中间一个子控件是否处于显示状态
state_last:控件包含多个子控件时,确定最后一个子控件是否处于显示状态
image.png
比如点赞的状态变化,单击点赞显示红色组件,再次单击显示灰色点赞组件
网友评论