安卓开发-基础篇(更新中)

安卓开发-基础篇

本篇文章算是自己学习的记录和补充,防止以后忘记。如果能够对大家有所帮助那就更好了。本文将会持续更新(根据本人的学习进度),如有问题,欢迎在评论区留言指正。

目录

目录

1.简单控件

1.1 文本显示(Text,Color)

1.1.1 简要介绍

这里的文本显示主要从两个方面来开始描述,一个是用于写界面的layout层部分,另外一个是正常的Java包部分。

  1. 在Layout层中,主要以XML形式来展现。常见的写法如下:

activity_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">
              <TextView
                        android:id="@+id"/tv_test"        <!--当前文字的唯一标识-->
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Hi!">               <!--用于修改当前的文字的内容-->
              </TextView>
                                           
</LinearLayout>

2.在后端的Java部分,可以这样来实现

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv_test=findViewById(R.id.test);
        tv_test.setText("你好!");//用于设置当前的文字
    }
}

此外,作为补充,在此简要介绍一下像素。

名称 解释
px(pixel)像素 称为图像元素,是作为图像构成的基本单元,单个像素的大小不固定,随屏幕大小和像素关系变化,一个像素点为1px。
Resolution(分辨率) 是指屏幕的垂直和水平方向的像素数量,如果分辨率是1920x1080,那就是垂直方向有1920个像素,水平方向有1080个像素。
Dpi(像素密度) 是指屏幕上每英寸(1英寸=2.54cm)距离中有多少个像素(具体的计算方式见下方)
Density(密度) 是指屏幕上每平方英寸(2.54^2平方厘米)中含有的像素点的数量。
Dip/dp(设备独立像素) 可以称为dp,长度单位,同一个单位在不同设备上会有不同的显示效果,与设备密度有关(计算方式在下方)

以4.95英寸1920x1080的手机为例:

Dpi:

  1. 计算直角边像素数量 19202+10802=2202^2
  2. 计算DPI:2202/4.95=445
  3. 则此设备的DPI为44(每英寸的距离中有445个像素)

Density:

上面得到每英寸中有440像素,即Density为每平方英寸中的像素数量,为445^2=198025

Dip:

所有显示在屏幕上的图片均以px为单位,Dip是我们开发中使用的长度单位,最后需要转化成px,1Dip的换算为:

px=dip x dip /160

换算可得:

320 x 480分辨率,3.6寸的手机:dpi为160,1dp=1px

以下是跳过证明的部分结论

  1. 对于相同分辨率的手机,屏幕越大,同DP的组件占用屏幕的比例就越小。
  2. 对于相同尺寸的手机,即使分辨率不同,同DP的组件占用屏幕的比例也相同。
  3. 根据官方的方法文档,官方的setTextSize方法使用的SP作为单位的。
1.1.2 文本颜色

官方给了部分颜色预设,在Java部分可以通过:

tv_test(TextView的变量名).setTextColor(Color.(可以挑选颜色)BLUE);

如果需要自定义颜色的话,可以通过查询颜色的RGB的16进制代码进行输入,具体如下:

tv_test(TextView的变量名).setTextColor(0xff00ff00);//八位表示显示,不透明绿色
tv_test(TextView的变量名).setTextColor(0x00ff00); //六位表示显示,透明绿色

而在前端XML部分,可以使用:

android:textColor="#000000"

1.2 视图 (android:layout_width; android:layout_height;)

1.2.1 视图宽高

在XML前端视图中,主要通过属性:

android:layout_width="wrap_content"
android:layout_height="wrap_content"

来进行实现,宽和高的取值主要有以下3种:

1.match_parent:表示与上级视图一致
2.wrap_content:表示与内容适应
3.以dp和px作为单位

而对于Java部分的来说,在确保XML界面已经设置完备后,需要依次执行以下步骤:

  1. 调用控件对象的getLayoutParams方法,来获取该控件的布局参数。
  2. 布局参数的width属性表示宽度,height属性表示高度,修改这两个属性值即可。
  3. 调用控件对象的setLayoutParams方法,填入修改后的布局使得参数生效。

具体代码样例如下

//获取tv_test的布局参数(含宽度和高度)
ViewGroup.LayoutParams params=tv_test.getLayoutParams();
//修改布局参数中的宽度数值,注意默认px单位,需要把dp数值转成px数值
params.width= Utils(自己建立的函数,需要自己去替换).dispDpToPx(this,300);
//设置tv_test的参数
tv_test.setLayoutParams(params);

其中,上文的dp转换px的函数如下

//根据手机的分辨率从dp的单位转换陈px(像素)
public static int dispDpToPx(Context context,float dpValue){
    //获取当前手机的像素密度(1个dp对应几个px)
    float scale=context.getResources().getDisplayMetrics().density;
    //四舍五入取整
    return (int)(dpValue*scale+0.5f);
}
1.2.2 视图间距

设置视图的间距主要有两种方式:

  • 采用layout_margin属性,其指定了当前视图与周围平级视图之间的距离。(包括layout_margin、layout_marginLeft、layout_marginTop、layout_marginRight、layout_marginBottom)-------指的是视图与外侧之间的距离。
  • 采用padding属性,它指定了当前视图与内部下级视图之间的距离。(包括padding、paddingLeft、paddingTop、paddingRight、paddingBottom)-------指的是视图与内侧之间的关系。
1.2.3 视图对齐方式

设置视图的对齐方式有两种方式:

  • 采用layout_gravity属性,它指定了当前视图相对于上级视图的对齐方式。
  • 采用gravity属性,它指定了下级视图相对于当前视图的对齐方式。
  • layout_gravity与gravity的取值包括:left、top、right、bottom,还可以用竖线来连接各取值,例如"left|top"即为向左上角对齐。

1.3 布局 (Layout)

1.3.1 线性布局LinearLayout

线性布局内部的各视图有两种排列方式:

  • orientation属性值为horizontal时,内部视图在水平方向从左到右排列。
  • orientation属性值为vertical时,内部视图在垂直方向从上向下排列。
  • 若不指定其属性值,默认水平方向排列。

实例:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    。。。中间为你写的实例部分

</LinearLayout>

在线性布局中,存在着权重的概念,即线性布局中的下级视图各自拥有多大比例的宽高。

其方式是layout_weight,但该属性不得在LinearLayout处设置,而在线性布局中的下级视图中进行设置,表示其下级视图在其中所占据的宽高比例。

  • layout_width填为0dp时,layout_weight表示其水平方向的宽度比例
  • layout_height填为0dp时,layout_weight表示其垂直方向的高度比例

此处仅举一个实例:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="竖排第一个!"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="竖排第二个!"
            />
    </LinearLayout>
</LinearLayout>
1.3.2 相对布局RelativeLayout

相对布局的下级视图位置由其他视图决定。用于确定下级视图位置的参照物分为以下两种:

  • 与该视图自身平级的视图;

  • 该视图的上级视图(也就是它归属的RelativeLayout)

如果不设定下级视图的参照物,那么下级视图默认显示在RelativeLayout的左上角。

有关的其他的具体实现方法可以去查询官方文档:https://developer.android.google.cn/reference/android/widget/RelativeLayout?hl=en#checkLayoutParams(android.view.ViewGroup.LayoutParams)

以下给出部分实例(具体情况可以参照以下实例慢慢调整)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="150dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="这是参照标签"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="水平中央"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:text="垂直中央"
        android:textSize="14sp" />

    <!--此左侧对齐会和顶部对齐重叠在一起-->
    <!--    <TextView
            android:id="@+id/tv_parent_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:text="与上级左侧对齐"
            android:textSize="14sp" />-->

    <TextView
        android:id="@+id/tv_parent_right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="与上级右侧对齐"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_parent_top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="与上级顶部对齐"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_parent_bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="与上级底部对齐"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_left_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/tv_center"
        android:layout_toLeftOf="@+id/tv_center"
        android:text="中间左边"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_right_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/tv_center"
        android:layout_toRightOf="@+id/tv_center"
        android:text="中间右边"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_above_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/tv_center"
        android:layout_alignLeft="@+id/tv_center"
        android:text="中间上边"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_bottom_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_center"
        android:layout_alignRight="@+id/tv_center"
        android:text="中间下边"
        android:textSize="14sp" />
</RelativeLayout>
1.3.3 网格布局GridLayout

网格布支持多行多列的表格排列。

网格布局默认从左向右,从上向下排列,新增了两个属性:

  • columnCount属性,它指定了网格的列数,即每行能放多少个视图;
  • rowCount属性,它指定了网格的行数,即每列能放多少个视图;

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="2"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="180dp"
        android:layout_height="60dp"
        android:text="浅红色"
        android:gravity="center"
        android:background="#ffcccc"
        android:textSize="14sp" />

    <TextView
        android:layout_width="180dp"
        android:layout_height="60dp"
        android:text="橙色"
        android:gravity="center"
        android:background="#ffaa00"
        android:textSize="14sp" />

    <TextView
        android:layout_width="180dp"
        android:layout_height="60dp"
        android:text="绿色"
        android:gravity="center"
        android:background="#00ff00"
        android:textSize="14sp" />
    <TextView
        android:layout_width="180dp"
        android:layout_height="60dp"
        android:text="深紫色"
        android:gravity="center"
        android:background="#660066"
        android:textSize="14sp" />
    <TextView
        android:layout_width="180dp"
        android:layout_height="60dp"
        android:text="天蓝色"
        android:gravity="center"
        android:background="#66ccff"
        android:textSize="14sp" />
</GridLayout>

PS:可以将前面所学的视图对齐给结合起来,自己试试。

1.3.4 滚动视图ScrollView

滚动视图有两种:

  • ScrollView,它是垂直方向的滚动视图;垂直方向滚动,layout_width属性值设置为match_parent,layout_height属性值设置为wrap_content。
  • HorizontalScrollView,它是水平方向的滚动视图;水平方向滚动时,layout_width属性值设置为wrap_content,layout_height属性值设置为match_parent。

具体的实例如下:

activitymain.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <!--水平滚动-->
    <HorizontalScrollView
        android:layout_width="wrap_content"
        android:layout_height="200dp">


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <View
                android:layout_width="300dp"
                android:layout_height="match_parent"
                android:background="#aaffff" />

            <View
                android:layout_width="300dp"
                android:layout_height="match_parent"
                android:background="#ffff00" />
        </LinearLayout>
    </HorizontalScrollView>

    <!--垂直滚动-->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <View
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:background="#66ccff" />

            <View
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:background="#ffff00" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

1.4 按钮(Button)

1.4.1 按钮控件基本介绍

按钮控件Button由TextView派生而来,它们之间的区别有:

  • Button拥有默认的按钮背景,而TextView默认没有背景;
  • Button内部文本默认居中对齐,TextView内部文本默认靠左对齐;
  • Button会默认将英文字母转成大写,而TextView保持原始的英文大小写。(PS:个人实测在目前的最新版2022.2.1.20中,按钮的大小写会正常显示,和文本一样。)

以下是两者的基本形式:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="以下展示按钮和文字的区别">
    </TextView>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="hi!">
    </Button>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is test obj">
    </TextView>
</LinearLayout>

与TextView相比,Button新增加了两个新属性:

  • textAllCaps:它指定了是否要将英文字母全部转为大写,true是对英文进行大写转换,false表示不做操作。

  • onClick:它用来接管用户的点击动作,指定了点击按钮需要触发什么方法。

1.4.2 直接点击按钮

此处直接给出演示:

此处是较为简单的演示,是事件并发,并不存在线程并发的问题;这些控件本身是线程不安全的,不会在多线程程序里面使用。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="以下是按钮方法">
    </TextView>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="直接点击按钮,使用onClick方式"
        android:onClick="doClick">
    </Button>
    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="此处查看按钮的点击结果">
    </TextView>
</LinearLayout>

PS:安卓的初始化主要放在onCreate函数中进行。

MainActivity.java

package com.demo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.demo.utils.DateUtil;

public class MainActivity extends AppCompatActivity {
    private TextView tv_result;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_result = findViewById(R.id.tv_result);

     }
    public void doClick(View view) {
        String desc=String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(),((Button)view).getText());
        tv_result.setText(desc);
    }
}

PS:DateUtil函数如下(自己编写的)

utils/DateUtil.java

package com.demo.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.SimpleFormatter;

public class DateUtil {
    public static String getNowTime(){
        SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
        return sdf.format(new Date());
    }
}

1.4.3 点击事件和长按事件
  • 监视器(泛指java中的各式Listener):指专门用于监控控件和动作行为。只有控件发生了指定的动作,监听器才会触发开关去执行对应的代码逻辑。

目前按钮控件中有两种常见的监听器:

  • 点击监听器,通过setOnClickListener方法来进行设置,当按钮被按住少于500ms,会触发点击事件。
  • 长按监听器,通过setOnLongClickListener方法来进行设置,当按钮被按住超过500ms,会触发长按事件。

PS:给按钮设置监听的时候,需要先去注册一下id。

1.点击事件部分

以下是实例展示部分:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/btn_click_single"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="指定单独的点击监听器">
    </Button>

    <Button
        android:id="@+id/btn_click_public"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自定义按钮--指定单独的点击监听器">
    </Button>

    <Button
        android:id="@+id/btn_click"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="常见实现方法--指定单独的点击监听器">
    </Button>

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:gravity="center"
        android:text="点击查看按钮显示内容">
    </TextView>
</LinearLayout>

MainActivity.java

package com.demo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.demo.utils.DateUtil;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tv_result;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_result = findViewById(R.id.tv_result);
        //一种较为底层
        Button btn_click_single = findViewById(R.id.btn_click_single);
        btn_click_single.setOnClickListener(new MyOnClickListener(tv_result));

        //公用操作
        Button btn_click_public=findViewById(R.id.btn_click_public);
        btn_click_public.setOnClickListener(this);

        //书上的常见操作---匿名内部类
        Button btn_click=findViewById(R.id.btn_click);
        btn_click.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String desc = String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(), ((Button) view).getText());
                tv_result.setText(desc);
            }
        });
    }

     //公用操作部分
    @Override
    public void onClick(View view) {
        if(view.getId()==R.id.btn_click_public){
            String desc = String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(), ((Button) view).getText());
            tv_result.setText(desc);
        }
    }

      //一种较为底层--自定义函数部分
    static class MyOnClickListener implements View.OnClickListener {
        private final TextView tv_result;
        public MyOnClickListener(TextView tv_result) {
            this.tv_result=tv_result;
        }
        @Override
        public void onClick(View view) {
            String desc = String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(), ((Button) view).getText());
            tv_result.setText(desc);
        }
    }
}
2.长按事件部分

注意点:

当接口中只有一个方法需要重写时,称其为函数式接口,而函数式接口可以使用lambda表达式(主要结构如下:

btn_long_click.setOnLongClickListener(view -> {
... 
return true;
});

具体实例如下:

MainActivity.java

package com.demo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.demo.utils.DateUtil;

public class MainActivity extends AppCompatActivity{
    private TextView tv_result;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_result = findViewById(R.id.tv_result);
        //书上的常见操作
        Button btn_long_click = findViewById(R.id.btn_longclick_single);
        btn_long_click.setOnLongClickListener(view -> {
            String desc = String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(), ((Button) view).getText());
            tv_result.setText(desc);
            return true;
        });
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/btn_longclick_single"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="指定长按点击监听器">
    </Button>

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:gravity="center"
        android:text="点击查看按钮显示内容">
    </TextView>
</LinearLayout>
1.4.4 禁用和恢复按钮

在实际的业务中,按钮通常有两种状态,即不可用和可用状态,它们在外观和功能上的区别如下:

  • 不可用按钮:按钮如果不许点击,即使点击无反馈,同时按钮文字为灰色。
  • 可用按钮:按钮允许点击,点击按钮会触发点击事件,同时按钮文字为正常的黑色。

是否允许点击由enabled属性控制,属性值为true时表示允许点击,false时表示不允许点击。

具体实例如下:

MainActivity.java

package com.demo;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.demo.utils.DateUtil;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_obj;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn_enable = findViewById(R.id.btn_enable);
        Button btn_disable = findViewById(R.id.btn_disable);

        btn_obj = findViewById(R.id.test_obj);
        TextView tv_result = findViewById(R.id.tv_result);

        btn_enable.setOnClickListener(this);
        btn_disable.setOnClickListener(this);
        btn_obj.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv_result.setText("已经点击测试按钮!");
            }
        });
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.btn_enable) {
            //启用当前控件
            btn_obj.setEnabled(true);
            //设置按钮的文字颜色
            btn_obj.setTextColor(Color.BLACK);
        } else if (id == R.id.btn_disable) {
            //关闭当前控件
            btn_obj.setEnabled(false);
            //设置按钮的文字颜色
            btn_obj.setTextColor(Color.GRAY);
        } else {

        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_enable"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="启动测试按钮"/>
        <Button
            android:id="@+id/btn_disable"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="关闭测试按钮"/>
    </LinearLayout>

    <Button
        android:id="@+id/test_obj"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="测试按钮"/>
    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这里查看测试按钮的点击结果"/>
</LinearLayout>

此处可能会出现的问题

如果你不想用if-else,而想用switch来进行R.id的判断。需要保证idfinal常量,否则会出现“constant expression required”导致无法运行。具体问题详解原文可以查询:switch case statement error: case expressions must be constant expression或者CSDN:https://blog.csdn.net/sinat_26820899/article/details/48878069

1.5 图像显示

1.5.1 图像视图ImageView

图像视图展示的图片通常位于res/drawable/*目录下,设置图像视图的显示图片有两种方式:

  • 在XML文件中,通过属性android:src设置图片资源,属性值格式形如“@drawable/不含拓展名的图片名称”。

  • Java中,通过调用setImageResource方法来设置图片资源,方法参数格式形如“R.drawable.不含拓展名的图片名称”。

MainActivity.java

package com.demo;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.demo.utils.DateUtil;

public class MainActivity extends AppCompatActivity{
    private Button btn_obj;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView iv_scale=findViewById(R.id.iv_scale);
        iv_scale.setImageResource(R.drawable.scene);

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--使用之前需要在res/drawable里面先放上自己所选择的图片-->
    <ImageView
        android:id="@+id/iv_scale"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:src="@drawable/scene"
        android:scaleType="fitXY"/>
</LinearLayout>

有关于图像视图的缩放问题,ImageView本身默认图片居中显示,可以通过scaleType属性设定。

具体的详细属性以及方法可以查询官方文档:https://developer.android.google.cn/reference/android/widget/ImageView.ScaleType?hl=en

1.5.2 图像按钮ImageButton

ImageButton是显示图片的图像按钮,但它继承自ImageView,并非继承Button。

ImageButton和Button之间的区别有:

  • Button既可以显示文本也可以显示图片,ImageButton只能显示图片但不能显示文本。
  • ImageButton上的图像可以按照比例缩放,而Buttton通过背景设置的图像会拉伸变形。
  • Button只能靠背景显示一张图片,而ImageButton可分别前景和背景显示图片,从而实现两张图片叠加的效果。

使用场景

有些字符无法使用输入法打出来,或者某些文字以特殊字体展示,适合使用图片将其放入到ImageButton之中。

ImageButton与ImageView之间的区别有

  • ImageButton有默认的按钮背景,ImageView默认没有背景。
  • ImageButton默认的缩放类型为center,而ImageView默认的缩放类型为fitCenter。

此处代码与上文代码较为类似,因此不再赘述。

1.5.3 同时展示文本和图像

同时展示文本和图像的可能途径包括:

  1. 利用LinearLayout对ImageView和TextView的组合布局。
  2. 通过按钮控件Button的drawable属性设置文本周围的图标。
  • drawableTop:指定文字上方的图片
  • drawableBottom:指定文字下方的图片
  • drawableLeft:指定文字左边的图片
  • drawableRight:指定文字右边的图片
  • drawablePadding:指定图片和文字的间距

以下是代码实例部分:(其余保持默认即可)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="图标在左"
        android:drawableLeft="@mipmap/ic_launcher"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="图标在右"
        android:drawableRight="@mipmap/ic_launcher"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="图标在上"
        android:drawableTop="@mipmap/ic_launcher"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="图标在下"
        android:drawableBottom="@mipmap/ic_launcher"/>
</LinearLayout>
1.5.4 小实战 计算器

需要用到前面5部分的大部分知识,模仿微软的计算器工具,做出一个简化版的计算器。

前端部分:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#EEEEEE"
    android:orientation="vertical"
    android:padding="5dp">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="简单计算器"
                android:textSize="20sp">
                <!--你可以扔到res的string中去,用@string/*代替简单计算器,使得代码具有一定保密性-->
            </TextView>
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:lines="3"
                android:text="0"
                android:textColor="@color/black"
                android:textSize="25sp"/>
            <GridLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:columnCount="4"
                android:rowCount="5">
                <!--本处自己在res/values下新建dimen.xml文件,canel指CE,可以直接把text换成CE也可-->
                <Button
                    android:id="@+id/btn_canel"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="@string/cancel"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>

                <Button
                    android:id="@+id/btn_divide"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="/"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>

                <Button
                    android:id="@+id/btn_multiply"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="x"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>

                <Button
                    android:id="@+id/btn_clear"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="C"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_7"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="7"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>

                <Button
                    android:id="@+id/btn_8"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="8"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_9"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="9"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>

                <Button
                    android:id="@+id/btn_plus"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="+"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_4"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="4"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_5"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="5"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_6"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="6"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_minus"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="-"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_1"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="1"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_2"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="2"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_3"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="3"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <!--随便从网上找的开根号的图片,本人命名为gen后,扔到了res/drawable内-->
                <ImageButton
                    android:id="@+id/btn_gen"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:src="@drawable/gen"
                    android:scaleType="centerInside"/>
                <!--          
                <Button
                    android:id="@+id/btn_sqrt"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="√"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>-->
                <Button
                    android:id="@+id/btn_1X"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="1/X"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_0"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="0"
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_dot"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="."
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
                <Button
                    android:id="@+id/btn_cal"
                    android:layout_width="0dp"
                    android:layout_height="@dimen/button_height"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="="
                    android:textColor="@color/black"
                    android:textSize="@dimen/button_font_size"/>
            </GridLayout>
        </LinearLayout>
    </ScrollView>
</LinearLayout>

为了方便管理按钮属性,在res/values下新建了dimens.xml文件,详细如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="button_font_size">30sp</dimen>
    <dimen name="button_height">75dp</dimen>
</resources>

其他按钮参考如下:https://developer.android.google.cn/guide/topics/ui/controls/button?hl=zh-cn

后端部分:(PS无法运行,逻辑不对,有空再改)

package com.demo;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.demo.utils.DateUtil;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tv_result;
    //第一个操作数
    private String firstNum = "";
    //运算符
    private String operator = "";
    //第二个操作数
    private String secondNum = "";
    //当前的计算结果
    private String result = "";
    //显示的文本内容
    private String showText = "";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //从布局文件中获取tv_result的文本视图
        tv_result = findViewById(R.id.tv_result);
        //下面给每个按钮控件都注册了点击监听器
        findViewById(R.id.btn_canel).setOnClickListener(this);
        findViewById(R.id.btn_0).setOnClickListener(this);
        findViewById(R.id.btn_1).setOnClickListener(this);
        findViewById(R.id.btn_2).setOnClickListener(this);
        findViewById(R.id.btn_3).setOnClickListener(this);
        findViewById(R.id.btn_4).setOnClickListener(this);
        findViewById(R.id.btn_5).setOnClickListener(this);
        findViewById(R.id.btn_6).setOnClickListener(this);
        findViewById(R.id.btn_7).setOnClickListener(this);
        findViewById(R.id.btn_8).setOnClickListener(this);
        findViewById(R.id.btn_9).setOnClickListener(this);
        findViewById(R.id.btn_1X).setOnClickListener(this);
        findViewById(R.id.btn_cal).setOnClickListener(this);
        findViewById(R.id.btn_clear).setOnClickListener(this);
        findViewById(R.id.btn_divide).setOnClickListener(this);
        findViewById(R.id.btn_dot).setOnClickListener(this);
        findViewById(R.id.btn_plus).setOnClickListener(this);
        findViewById(R.id.btn_minus).setOnClickListener(this);
        findViewById(R.id.btn_multiply).setOnClickListener(this);
        findViewById(R.id.btn_sqrt).setOnClickListener(this);


    }

    @Override
    public void onClick(View view) {
        String inputText;
        if (view.getId() == R.id.btn_sqrt) {
            inputText = "√";
        } else {
            inputText = ((TextView) view).getText().toString();
        }
        int id = view.getId();
        if (id == R.id.btn_clear) {
            //清除
            clear();
        } else if (id == R.id.btn_canel) {
            //取消
        } else if (id == R.id.btn_plus || id == R.id.btn_minus || id == R.id.btn_multiply ||
                id == R.id.btn_divide) {
            //加减乘除
            operator=inputText;//运算符
            refreshText(showText);
        } else if (id == R.id.btn_cal) {
            //等号
            double calculate_result=calculateFour();
            refreshOperate(String.valueOf(calculate_result));
            refreshText(showText+"="+result);
        } else if (id == R.id.btn_sqrt) {
            //开根
            double sqrt_result=Math.sqrt(Double.parseDouble(firstNum));
            refreshOperate(String.valueOf(sqrt_result));
            refreshText(showText+"="+result);
        } else if (id == R.id.btn_1X) {
            //求倒数
            double reciprocal_result=1.0/Double.parseDouble(firstNum);
            refreshOperate(String.valueOf(reciprocal_result));
            refreshText(showText+"√="+result);
        } else {
            //上次的运算结果已经出来了
            if(result.length()>0&&operator.equals("")){
                clear();
            }

            //点击数字或者小数点
            if (operator.equals("")) {
                //无运算符,则继续拼接第一个操作数
                firstNum = firstNum + inputText;
            } else {
                //有运算符,则继续拼接第二个操作数
                secondNum = secondNum + inputText;
            }
            //整数不需要前面的0
            if (showText.equals("0") && inputText.equals(".")) {
                refreshText(inputText);
            } else
                refreshText(showText + inputText);
        }
    }

    //四则运算
    private double calculateFour() {
        if(operator=="+"){
            return Double.parseDouble(firstNum)+Double.parseDouble(secondNum);
        }else if(operator=="-"){
            return Double.parseDouble(firstNum)-Double.parseDouble(secondNum);
        }else if(operator=="x"){
            return Double.parseDouble(firstNum)*Double.parseDouble(secondNum);
        }else if(operator=="/"){
            return Double.parseDouble(firstNum)/Double.parseDouble(secondNum);
        }else {
            System.out.println("非四则运算");
        }
        return 0;
    }

    //清除数据并且初始化
    private void clear(){
        refreshOperate("");
        refreshText("");
    }

    //刷新运算结果
    private void refreshOperate(String new_result){
        result=new_result;
        firstNum=result;
        secondNum="";
        operator="";
    }
    //刷新文本显示
    private void refreshText(String text) {
        showText = text;
        tv_result.setText(showText);
    }
}

2. 活动Activity

2.1 Activity启停活动页面

2.1.1 Activity的启动和结束

1.从当前页面跳转至新页面,代码如下:

  • startActivity(new Intent(源界面.this,目标页面.class));

2.从当前页面回到上一个界面,相当于关闭当前界面,返回代码如果代码如下:

  • finish(); //结束当前的活动页面

MainActivity.java

package com.wu.prc;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

 public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_act_next).setOnClickListener(this);
    }

     @Override
     public void onClick(View view) {
         startActivity(new Intent(MainActivity.this,MainActivity2.class));
     }
 }

MainActivity2.java

package com.wu.prc;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

 public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_act_next).setOnClickListener(this);
    }

     @Override
     public void onClick(View view) {
         startActivity(new Intent(MainActivity.this,MainActivity2.class));
     }
 }

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_act_next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="跳转至下个界面"/>

</LinearLayout>

activity_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity2">

    <ImageView
        android:id="@+id/iv_back"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:padding="5dp"
        android:src="@drawable/ic_back"/>

    <Button
        android:id="@+id/btn_finish"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="完成"/>
</LinearLayout>
2.1.2 Activity的生命周期

Activity的生命周期是指Activity从创建到销毁的整个过程,这个过程一般分为五个状态。以下是生命周期的基本状态和常用的周期方法。

1.启动状态
onCreate()

Activity创建时调用,进性初始化设置。而当Activity启动,则不可见。

onStart()

Activity即将可见时调用,而Activity可见,不能进行交互。

2.运行状态

Activity处于界面的最前端,他是可见,有焦点的,可以与用户交互的。
Activity处于运行状态时,Android会尽可能的保持这个状态,即使内存不足的情况,Android也会优先销毁栈底的Activity。

3.暂停状态

Activity对用户来说仍然可见,但是无法获取焦点,对用户对他的操作没有反应,此时它处于暂停状态。

onResume()

Activity获取焦点时调用。当Activity可见,可交互。

onPause()

当前Activity被其他Activity覆盖或屏幕锁屏时调用。Activity暂停。

4.停止状态

Activity完全不可见,它处于停止状态。

onStop()

Activity停止。Activity不可见,后台运行。

5.销毁状态

Activity将被清理出内存。

onDestroy()

Activity销毁时调用。

onRestart()

Activity从停止状态到再次启动时调用。

onNewIntent()

重用已有的活动实例。

img

2.1.3 Activity的启动模式(此模块后期仍需注解和增补)

打开新页面的方法调用顺序为:

  • onCreate--->onStart--->onResume

关闭旧页面的方法调用顺序为:

  • onPause--->onStop--->onDestroy

主要有两种跳转方式:

     @Override
     public void onClick(View view) {
        Intent intent=new Intent(this,MainActivity2.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
     }

或者

        findViewById(R.id.btn_act_next).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent(this,MainActivity2.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
            }
        });

Activity的动态/静态启动模式

动态设置与静态设置的区别

静态设置:在Manifest(XML)中进行配置,在活动执行前进行配置(这里可能描述的不够准确)。

动态设置:在JAVA中,通过设立Flag来进行启动。

1.主要有以下几种静态跳转模式:
1.1 默认启动模式standard

该模式可以被设定,不在manifest设定时候,Activity的默认模式就是standard。在该模式下,启动的Activity会依照启动顺序被依次压入Task中。

img

1.2 栈顶复用模式singleTop

在该模式下,如果栈顶Activity为我们要新建的Activity(目标Activity),那么就不会重复创建新的Activity。

img

1.3 栈内复用模式singleTask

与singleTop模式相似,只不过singleTop模式是只是针对栈顶的元素,而singleTask模式下,如果task栈内存在目标Activity实例,则:

  • 将task内的对应Activity实例之上的所有Activity弹出栈。
  • 将对应Activity置于栈顶,获得焦点。

img

1.4 全局唯一模式singleInstance(较为复杂!)

在该模式下,我们会为目标Activity分配一个新的affinity,并创建一个新的Task栈,将目标Activity放入新的Task,并让目标Activity获得焦点。新的Task有且只有这一个Activity实例。 如果已经创建过目标Activity实例,则不会创建新的Task,而是将以前创建过的Activity唤醒(对应Task设为Foreground状态)

img

2.动态设置启动模式

通常的话,如果需要使用的话,具体如下:

intent.setFlags(.....);

然后根据个人需要的情况向里面添加Flag即可,以下介绍部分常见的Flag。

2.1 NEW_TASK
Intent.FLAG_ACTIVITY_NEW_TASK

这个Flag同singleInstance相似:在给目标Activity设立此Flag后,会根据目标Activity的affinity进行匹配:如果已经存在与其affinity相同的task,则将目标Activity压入此Task。反之没有的话,则新建一个task,新建的task的affinity值与目标Activity相同。然后将目标Activity压入此栈。即若有与affinity相同的task,则就地放入task,没有会新建task将Activity放入。
此外,其与singleInstance有一定区别:

1.新的Task没有说只能存放一个目标Activity。只是说决定是否新建一个Task。而singleInstance模式下新的Task只能放置一个目标Activity。
2.在同一应用下,如果Activity都是默认的affinity,那么此Flag无效。而singleInstance默认情况也会创建新的Task。
具体说明,建议看他人文章:https://blog.csdn.net/zy_jibai/article/details/80587083

2.2 SINGLE_TOP
Intent.FLAG_ACTIVITY_SINGLE_TOP

此效果和singleTop相同,若栈顶拥有,则不会重复创建新Activity

2.3 CLEAR_TOP
Intent.FLAG_ACTIVITY_CLEAR_TOP

此flag同singleTask类似,当设置此Flag时,目标Activity会检查Task中是否存在此实例,如果没有则添加压入栈,如果有,就将位于Task中的对应Activity其上的所有Activity弹出栈,此时有以下两种情况:

  • 如果同时设置Flag_ACTIVITY_SINGLE_TOP,则直接使用栈内的对应Activity,
  • 若没有设置,则将栈内的对应Activity销毁重新创建。

2.2 在活动之间传递消息

2.2.1 显式Intent和隐式Intent

Intent是各个组件之间沟通的桥梁,它用于Android各组件之间的通信,主要完成下列工作:

  • 表明本次通信请求从哪里来、到哪里去、要怎么走。
  • 发起方携带本次通讯所需要的数据内容,接收方从收到的意图中解析数据。
  • 发起方若想判断接收方的处理结果,意图就要负责让接收方传回应答的数据内容。

Intent的主要组成部分:

元素名称 设置方法 说明和用途
Component setComponent 组件,它意图的来源与目标
Action setAction 动作,它指定意图的动作行为
Data setData 即URL,它指定的动作要操作的数据路径
Category addCategory 类别,它指定意图的操作类别
Type setType 数据类型,它指定消息的数据类型
Extras putExtras 拓展信息,它指定装载的包裹信息
Flags setFlags 标志位,它指定活动的启动标志
显式Intent

显式Intent,直接指定来源活动与目标活动,属于精确匹配。它有三种构建方式:

  • 在Intent的构造函数中指定

    Intent intent=new Intent(this,ActNextActivity.class); //创建一个目标确定的意图
    
  • 调用意图对象的setClass方法指定

    Intent intent=new Intent();  //创建一个新意图
    intent.setClass(this,ActNextActivity.class);  //设置意图要跳转的目标活动
    
  • 调用意图对象的setComponent方法指定

    Intent intent=new Intent();  //创建一个新意图
    //创建包含目标活动在内的组件名称对象
    ComponentName component=new ComponentName(this,ActNextActivity.class);
    intent.setComponent(component);  //设置意图携带的组件信息
    
隐式Intent

没有明确指定要跳转的目标活动,只给出一个动作字符串让系统自动匹配,属于模糊匹配。通常App不希望向外部暴露活动名称,只给出一个事先定义好的标记串,按照约定俗成的方式进行跳转,隐式Intent便起到了标记过滤的作用。此动作为标记串,可以自定义动作,也可以是已有的动作,具体如下表:

Intent系统动作常量名 系统动作常量值 说明
ACTION_MAIN android.intent.action.MAIN App启动时的入口
ACTION_VIEW android.intent.action.VIEW 向用户显示数据
ACTION_SEND android.intent.action.SEND 分享内容
ACTION_CALL android.intent.action.CALL 直接拨号
ACTION_DIAL android.intent.action.DIAL 准备拨号
ACTION_SENDTO android.intent.action.SENDTO 发送短信
ACTION_ANSWER android.intent.action.ANSWER 接听电话

此处主要写的是Java的部分,目的是跳转至本应用之外的应用

MainActivity2.java

package com.wu.prc;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity2 extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        findViewById(R.id.btn_dial).setOnClickListener(this);
        findViewById(R.id.btn_sms).setOnClickListener(this);
    }

    @Override
    public void onClick(View view){
        int id=view.getId();
        Intent intent=new Intent();
        if(id==R.id.btn_dial){
            //设置意图动作为准备拨号
            intent.setAction(Intent.ACTION_DIAL);
            Uri uri=Uri.parse("tel:119"+"12345");
            intent.setData(uri);
            startActivity(intent);
        }else if(id==R.id.btn_sms){
            //设置意图动作为发短信
            intent.setAction(Intent.ACTION_SENDTO);
            //声明一个发送短信的Uri
            Uri uri2=Uri.parse("smsto:"+"12345");
            intent.setData(uri2);
            startActivity(intent);
        }
    }
}

activity_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity2">
    <Button
        android:id="@+id/btn_dial"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="打开拨号界面"/>

    <Button
        android:id="@+id/btn_sms"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="打开短信界面"/>
</LinearLayout>

PS:此外,还可以使用default来跳转至自定义的界面,通过此方法可以从A应用跳转至B应用。

AndroidMainifest.xml(你希望跳转的应用内的)

        <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>
            
            <intent-filter>
                <action android:name="android.intent.action.NING"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

你当前操作的应用的Java文件

Intent intent=new Intent();
intent.setAction("android.intent.action.NING");
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
2.2.2 向下一个Activity发送数据
  • Intent使用Bundle对象存放待传递的数据信息。

  • Bundle对象操作各类型数据的读写方法:

数据类型 读方法 写方法
整型数 getInt putInt
浮点数 getFloat putDouble
双精度数 getDouble putDouble
布尔值 getBoolean putBoolean
字符串 getString putString
字符串数组 getStringArray putStringArray
字符串列表 getStringArrayList putStringArrayList
可序列化结构 getSerializable getSerializable

此处仅展示Java部分:

发送数据的部分

package com.wu.prc;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity2 extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        tv_send=findViewById(R.id.tv_send);
        findViewById(R.id.btn_send).setOnClickListener(this);
    }

    @Override
    public void onClick(View view){
        Intent intent = new Intent(this,ActReceiveActivity.class);
        //创建新包裹
        Bundle bundle = new Bundle();
        bundle.putString("request_time",DateUtil.getNowTime());//是手机内部的实际时间,不一定是现实的实际时间,
        bundle.putString("request_content",tv_send.getText().toString());
        intent。putExtras(bundle);
        startActivity(intent);
    }
}

接受数据的部分

package com.wu.prc;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class ActReceiveActivity extends AppCompatActivity{

    private TextView tv_receive;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_act_receive);
        tv_receive=findViewById(R.id.tv_receive);
        Bundle bundle=getIntent().getExtras();
        String request_time=bundle.getString("request_time");
        String request_content=bundle.getString("request_content");
        String desc=String.format("收到请求消息:\n请求时间%s\n请求内容为%s",request_time,request_content);
        tv_receive.setText(desc);
    }
}

=2023/7/3更新=================

2.3 为活动补充附加信息

2.3.1 利用资源文件配置字符串

利用res文件夹下的strings.xml文件来有效的替代程序中的特定字符串,可以有效的提高程序的安全性。

2.3.2 利用元数据传递配置信息
2.3.3 给应用页面注册快捷方式

=2024/1/28更新=================
现在实际中开始使用UNIAPP开发了,这个到时候用到再更新吧

参考文章/文献:

1.CSDN.https://blog.csdn.net/sinat_26820899/article/details/48878069

2.CSDN.https://blog.csdn.net/l1934499576/article/details/115677568

3.CSDN.https://blog.csdn.net/zy_jibai/article/details/80587083

posted @ 2023-07-03 21:11  NaHC03  阅读(21)  评论(0编辑  收藏  举报