《第一行代码》Android开发入门--探究活动

401 阅读11分钟

1 创建项目

用Android Studio创建项目,大致步骤如下

本着学习的目的,这里创建一个空的项目
因为之前我已经创建这个项目了,所以左下角会有警告,这里只做演示,不重复创建了。如果没有特殊需要,项目名和项目存放目录确定好之后就可以点击Finish了

2 快速创建活动和布局

左侧展开的目录结构我这里切换到是Project模式,默认是Android模式

创建一个空的活动,活动名是FirstActivity,选择自动生成布局文件,然后Finish

FirstActivit文件的代码如下所示

public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    }

3 创建布局

点开res\layout\activity_first.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=".FirstActivity">

    <Button
        android:id="@+id/button_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="button 1"
        />
</LinearLayout>

LinearLayout是线性布局,后面细讲布局方式

android:layout_width="match_parent"表示当前元素的宽度和父元素一样宽,这里指屏幕宽度

android:layout_height="match_parent"表示当前元素的高度和父元素一样高,这里指屏幕高度

这里添加了button元素,并添加了几个属性

android:id="@+id/button_1"是给当前元素定义一个唯一的标识符,之前可以通过该id拿到这个元素进行操作

android:layout_height="wrap_content"表示当前元素的高度只要能刚好包含里面的内容就行

android:text="button 1"是该元素里显示的文本内容,默认里面的英文全部转换成大写显示,如果想按照我们输入的显示出来,那就得加上android:textAllCaps="false"这行代码

现在我们可以通过右侧栏的Preview来展示当前布局的

加载布局

布局创建完成后还需要在活动中引入,在FirstActivity的onCreate方法中 调用setContentView()来给当前活动加载一个布局,方法中一般会传入一个布局文件的id

public class FirstActivity extends AppCompatActivity {

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

项目中添加的任何资源文件都会在R文件中生成一个相应的资源id,这里可需要调用R.layout.activity_first就可以得到activity_first.xml这个文件的id

注册活动

所有的活动都需要在AndroidManifest.xml中注册才能生效,我们打开app\src\main\AndroidManifest.xml,代码如下所示

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".FirstActivity">
        </activity>
    </application>

</manifest>

活动的注册声明是要放在<application>这个标签里面,是通过 标签来进行注册的,这里Android Studio已经帮我们注册好了,通过android:name来指定俱体注册哪一个活动,这里的.FirstActivity就相当于com.example.activitytest.FirstActivity的缩写,由于<manifest>标签中已经通过package属性指定了程序的包名com.example.activitytest,因此注册的时候这一部分就可以省略,直接写.FirstActivity就可以了

接下来还需要给程序配置主活动,就是当程序启动时首先运行的那个活动,在</activity>标签内部添加<intent-filter>标签,并在标签里添加如下两行代码进行声明

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

我们还可以使用android:label指定活动中标题栏的内容

修改后的AndroidManifest.xml文件,代码如下所示

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".FirstActivity"
            android:label="这是标题">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

运行结果如下

这里按钮上的文本之所以全部大写是因为我运行程序截图的时候并代码中并没有加入 android:textAllCaps="false"

在活动中使用Toast

我们需要点击按钮的时候弹出Toast,代码中的注释已经解释的很清楚了,代码如下所示

   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
//        通过findViewById()获取到布局文件中定义的元素,返回View对象;
//        这里要向下转型成Button对象,得到按钮实例
        Button button1 = (Button) findViewById(R.id.button_1);
//        为按钮注册一个监听器
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                在活动中使用Toast
//                通过静态方法makeText创建出一个Toast对象,然后调用show()方法将Toast显示出来
//                makeText()有三个参数,第一个参数是Context(上下文,这里活动本身就是一个Context对象,所以传入FirstActivity.this)
//                第二个参数是Toast显示的文本内容,
//                第三个参数是Toast显示的时长,有两个内置常量可以选择Toast.LENGTH_SHORT和 Toast.LENGTH_LONG
                Toast.makeText(FirstActivity.this, "You clicked Button", Toast.LENGTH_SHORT).show();
}
}
}

运行程序点击按钮即可看到效果(不出意外的话~)

在活动中使用Menu

因为我已经创建过了,所以不重复创建,只做演示

在res目录下新建一个menu文件夹

menu目录下新建一个main菜单文件

然后在main.xml中添加如下代码

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/add_item"
        android:title="Add" />
    <item
        android:id="@+id/remove_item"
        android:title="Remove_item"/>
</menu>

<item>中的两个属性都不需要过多解释了吧,看属性名大致都可以猜到了 回到FristActivity中重写onCreateOptionsMenu()方法,重写方法可用快捷键Ctrl+O(windoms)

代码如下所示

   @Override
    public boolean onCreateOptionsMenu(Menu menu) {
//        通过getMenuInflater()方法来得到MenuInflater对象,再调用该对象中的inflate()方法就可以给该活动创建菜单了
//        inflate接收两个参数,第一个参数指定我们通过哪一个资源文件来创建菜单
//        第二个参数用于指定我们的菜单项添加到哪一个Menu对象当中,这里直接使用传入的menu参数
        getMenuInflater().inflate(R.menu.main, menu);
//        参加true,表示允许创建的菜单显示出来,若为false则无法显示
        return true;
    }

看注释,不再赘述

让菜单显示还不够,我们还要再定义菜单响应事件,在FirstActivity中重写onOptionsItemSelected()方法,代码如下

   @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.add_item:
                Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show();
                break;
            case R.id.remove_item:
                Toast.makeText(this, "You clicked Remove", Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }

运行效果如下

销毁一个活动

活动销毁有2种方式,一个是直接点击Back键,另一种是用finish()方法 ,修改按钮监听器中的方法

  button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });

使用Intent在活动之间穿梭

我们之前使用的就只有一个主活动,下面来学习如何从一个活动跳转到另一个活动 使用显示Intent 新建一个名为SecondActivity的活动,方式跟创建FirstActivity活动一样

编辑activity_second.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=".SecondActivity">

    <Button
        android:id="@+id/button_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="button 2"
        />
</LinearLayout>

修改FirstActivity中按钮的点击事件,代码如下所示:

    button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

//                使用Intent在活动之间穿梭
//                Intent的这个构造函数接收两个参数,
//                第一个参数:要求提供一个启动活动的上下文
//                第二个参数:指定想要启动的目标活动
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
//                startActivity()专门用于启动活动的,它接收一个Intent参数
                startActivity(intent);
            }
        });

运行结果

隐式Intent

隐式Intent并不明确指出我们想要启动哪个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动

在AndroidManifest.xml文件的<activity>标签下的<intent-filter>标签里可以指定当前活动可以启动的action和category

  <activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.example.activitytest.ACTION_START" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

只有<action>和<category>中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应Intent

修改FirstActivity中按钮的点击事件,代码如下:

    button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                使用隐式Intent
//                使用另一个Intent构造函数,直接将action的字符串传入
//                表明我们们想要启动能够响应com.example.activitytest.ACTION_START这个ation的活动
                Intent intent = new Intent("com.example.activitytest.ACTION_START");
//                startActivity()专门用于启动活动的,它接收一个Intent参数
                startActivity(intent);
            }
        });

android.intent.category.DEFAULT是一种默认的category,在调用startActivity()方法的时候会自动将这个category添加到Intent中

重新运行程序,在FirstActivity界面点击按钮同样可以成功启动SecondActivity

第一个Intent只能指定一个action,但可以指定多个category,那么现在再来添加一个吧,打开AndroidManifest.xml添加这行代码

<android:name="com.example.activitytest.MY_CATEGORY" />

在FirstActivity中按钮的点击事件中添加如下代码

intent.addCategory("com.example.activitytest.MY_CATEGORY");

更多隐式Intent的用法

使用隐式Intent不仅可以启动自己程序内的活动中,还可以启动其他程序的活动

1)比如说你的应用程序需要展示一个个网页,只需要调用系统的浏览器打开这个网页就行了

修改FirstActivity中按钮点击事件的代码,代码如下

     button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("http://www.baidu.com"));
                startActivity(intent);
            }
        });

这里指定了Intent的action是Intent.ACTION_VIEW,这是Android系统的内置动作,通过Uri.parse()方法将一个网址字符串解析成一个Uri对象,再调用Intent的setData()方法将这个Uri对象传递进去

重新运行程序,运行结果如下

2)调用系统的拨号界面

修改FirstActivity.xml中按钮的点击事件,代码如下所示

     button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:10086"));
                startActivity(intent);
            }
        });

这里指定了Intent的action是Intent.ACTION_DIAL,这也是Android系统的内置动作

重新运行程序,运行结果如下

向下一个活动传递数据

假设FirstActivity中有一个字符串,要将它传递到SecondActivity当中,可以这样实现

修改FirstActivity中按钮的点击事件的代码

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                String data="Hello SecondActivity";
                intent.putExtra("extra_data",data);
                startActivity(intent);
            }
        });

这里使用显示Intent启动SecondActivity,并通过putExtra()方法传递了一个字符串, putExtra()方法接收两个参数,第一参数是键,第二参数是值

修改SecondActivity中的代码如下

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
//        可以通过getIntent()获取到用于启动SecondActivity活动的Intent
        Intent intent = getIntent();
        String extra_data = intent.getStringExtra("extra_data");
        Log.d("SecondActivity","++++++"+extra_data);
    }

可以通过getIntent()获取到用于启动SecondActivity活动的Intent,然后通过getStringExtra()方法,传入相应的键值,就可以得到传递的数据了,如果传递的数据是整型,用getIntExtra()方法来接收,以此类推

重新启动程序并点击按钮,查看logcat会打印出相应的信息

返回数据给上一个活动

startActivityForResult()也是用来启动活动的,这个方法可以在活动被销毁的时候向上一个活动返回一个结果,startActivityForResult()方法接收两个参数,第一个是Intent,第二个是请求码,请求码必须要是唯一值,用于在之后的回调中数据的判断

修改FirstActivity中按钮的点击事件,代码如下所示

      button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                startActivityForResult(intent,1);
            }
        });

给SecondActivity中的按钮注册点击事件,并在点击事件中添加返回数据的逻辑,代码如下所示

     button2.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.putExtra("data_result", "Hello FirstActivity");
                setResult(RESULT_OK,intent);
                finish();
            }
        });

创建了一个Intent,没有指定任何“意图”,仅用于传递数据。setResult()专门用来给上一个活动返回数据的,接收两个参数,第一个参数用于向上一个活动返回处理结果,通常只使用RESULT_OK和RESULT_CANCELED这两个值,第二个参数是把带有数据的Intent传递回去,然后使用finish()来销毁当前活动

由于使用startActivityForResult()方法来启动活动,当启动的活动被销毁的时候,会回调上一个活动的onActivityResult()方法,因此这里我们需要在FirstActivity中重写这个方法来得到返回的数据

   @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch (requestCode)
        {
            case  1:
                if(resultCode== RESULT_OK)
                {
                    String returnedData = data.getStringExtra("data_result");
                    Log.i("FirstActivity", returnedData);
                }
                break;
                default:
        }

onActivityResult()方法带有有三个参数,第一个参数requestCode,即我们启动活动时传入的请求码。第二个参数resultCode,即我们在返回数据时传入的返回结果。第三个参数data,即携带着返回数据的Intent

由于在一个活动中可能用startActivityForResult()方法去启动了多个不同的活动,每个活动返回的数据都会回调到onActivityResult()中,所以我们需要通过requestCode来判断数据来源,确定数据是从SecondActivity返回之后,再通过resultCode来判断处理结果是否成功,最后从data中取值并打印出来

重新运行程序,在FirstActivity中点击按钮到SecondActivity页面,再在SecondActivity界面点击按钮回到FirstActivity,查看logcat打印的信息,会打印出相应的信息的

如果这里通过点击Back键回到FirstActivity界面并没有返回数据,解决方式很简单,在SecondActivity中重写onBackPressed()方法,代码如下所示

 @Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("data_result", "Hello FirstActivity");
        setResult(RESULT_OK,intent);
        finish();
    }

内容参考自《第一行代码》

github代码

码云代码

个人网站:www.panbingwen.cn