赞
踩
Android
端应用,以笔记(便签)为例。Windows10
Android Studio
,版本:2022.3.19Java
(版本:17)Android
)但无从下手的人
Java
环境Android Studio
Android Studio
新建了第一个文件并成功类似输出Hello World!
Java
Android Studio
项目结构Java
部分语法和XML
文件的撰写点击上图中的悬浮按钮后,将跳转页面,见下图;
如上图所示,你可以在此界面编写。
芜湖!写好喽!
接下来,点击手机(AVD)的后退按键,你将在
logcat
界面见到你输入的信息(见下图)。记得筛选词哦~~
如你所见,本文章完成的仅是记事本的雏形,你可以根据自己实际需要选择继续阅读本文或停止阅读本文。
默认情况下,Android Studio
会在 Android
视图中显示您的项目文件。此视图并未反映磁盘上的实际文件层次结构。相反,它按模块和文件类型进行整理,以简化项目的关键源文件之间的导航方式,并隐藏某些不常用的文件或目录。
Android
视图与磁盘上的结构之间的一些结构差异在于 Android
视图:
在顶级 Gradle Script
组中显示项目的所有与构建相关的配置文件。
在模块级组中显示每个模块的所有清单文件(当您针对不同的产品变种和 build
类型使用不同的清单文件时)。
在一个组(而非在每个资源限定符的单独文件夹)中显示所有备用资源文件。例如,启动器图标的所有密度版本都可以并排显示。
在每个 Android
应用模块中,文件显示在以下组中:
manifests
包含 AndroidManifest.xml
文件。
java
包含 Kotlin
和 Java
源代码文件(以软件包名称分隔各文件,包括 JUnit
测试代码)。
res
包含所有非代码资源(例如 XML
布局、界面字符串和位图图像),这些资源划分到相应的子目录中。如需详细了解可能的资源类型,请参阅应用资源概览。
Android Studio
项目结构包括许多目录和文件,每个都有不同的用途和功能。下面是一个更详细的介绍,包括每个目录和文件:
.app 目录:
manifests 目录:
java 目录:
其他com.example.my_notes_record 目录:没啥用,就测试用的,平时没事也用不着。
Gradle Scripts 目录:
AndroidManifest.xml
文件是 Android 应用程序的核心配置文件。
这个文件能干啥?
Activity
、Service
和 Broadcast Receiver
。Activity
。Intent
过滤器,使应用程序能够与其他应用程序交互。com.example.my_notes_record
这个是包名
这个目录下将存放你要使用或新建的Java
文件
该目录下的众多xml
文件实质上就是图片。
下面展示新建vector assert
此目录下的众多xml
文件用于布局。
每一个xml
文件都与一个app/java/com.example.my_notes_record 目录下的Java文件对应。
例如:
//app/java/com.example.my_notes_record/MainActivity.java
package com.example.my_notes_record;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
<!-- app/res/layout/activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.412" />
</androidx.constraintlayout.widget.ConstraintLayout>
解释如下:
MainActivity.java
(Java 代码文件):这个文件就像是一位魔术师,他负责控制和管理整个表演。他知道要在哪里放置道具,何时进行魔术动作,以及如何与观众互动。
activity_main.xml
(XML 布局文件):这个文件就像是魔术师的道具箱,里面有各种道具和说明书。在道具箱中,有一块特殊的纸张,上面写着:“在舞台上放置一个名为 ‘Hello World!’ 的文本,并将它放在舞台的中央底部。”
现在,让我们看看它们如何联系起来:
MainActivity.java
)在表演开始时打开了他的道具箱(activity_main.xml
)。更直白的说:
在 MainActivity.java
文件的 onCreate
方法中,通过以下代码行:
setContentView(R.layout.activity_main);
告诉 Android 在此活动中使用名为 activity_main.xml
的布局文件作为用户界面的布局。
在 activity_main.xml
文件中,定义了一个 TextView
,其中包含 “Hello World!” 文本。这个 TextView
的属性和布局约束决定了它在屏幕上的位置和外观。
因此,这两个文件的联系在于,MainActivity.java
使用 activity_main.xml
作为其界面的布局。当 MainActivity
运行时,它会加载并显示 activity_main.xml
中定义的用户界面,用户将看到带有 “Hello World!” 文本的界面。
啰里啰唆,简单说就是Java 代码控制着界面的行为和逻辑,而 XML 布局文件定义了界面的外观和布局。通俗意义上说就是前后端分离,二者通过 setContentView(R.layout.activity_main);
链接在一起。
接下来对 setContentView(R.layout.activity_main);
解释如下:
setContentView
是一个 Android Activity 类的方法,它用于设置当前 Activity 所显示的用户界面(UI)的布局。
R.layout.activity_main
是一个引用,它指向了一个在 res/layout
目录下的 XML 布局文件,即应用程序主界面的布局文件。
R
代表 “资源”(Resource)的缩写。它是一个由 Android 自动创建的类,包含了应用程序中使用的各种资源的引用,如布局、图像、字符串、颜色等。
R.layout
是 R
类中的一个内部类,用于引用布局文件。在 R.layout
中,每个布局文件都会分配一个唯一的整数标识符(ID),以便在代码中引用。
当调用 setContentView(R.layout.activity_main);
时,Android 系统会加载并显示 activity_main.xml
布局文件中定义的用户界面。
换句话说,这行代码告诉 Android 系统将 activity_main.xml
文件中定义的布局设置为当前 Activity 的界面,使用户可以看到该界面。
当涉及到 app/res/values
目录和 Gradle Scripts/build.gradle (Module: app)
文件时,这两者的简单解释如下:
app/res/values 目录:
这是 Android 应用程序中的一个目录,用于存储各种资源的值,如字符串、颜色、尺寸等。它是用来集中管理应用程序的可配置数据的地方。
在这个目录中,您会找到 strings.xml
、colors.xml
、dimens.xml
等文件,它们分别用于存储应用程序中使用的字符串、颜色和尺寸信息。
使用这个目录有助于应用程序的国际化和主题化,因为您可以在不同的文件夹中存储不同语言的字符串,或者在不同的文件中定义不同的颜色和尺寸,从而使应用程序更具灵活性和可维护性。
注意:在 app/res/values
目录中,您可以创建自定义的 XML 文件,但这些文件必须符合一定的规则和命名约定。一般来说,values
目录用于存储字符串、颜色、尺寸等资源的值,这些资源通常以 XML 文件的形式进行存储。
以下是一些常见的 values
目录中的 XML 文件命名约定:
strings.xml:用于存储应用程序中的字符串资源,如界面标签、按钮文本等。这个文件是必需的,通常包含默认语言的字符串资源。
colors.xml:用于存储颜色值的资源。您可以在这个文件中定义应用程序使用的颜色,以便在布局文件和代码中引用。
dimens.xml:用于存储尺寸值的资源。这个文件可以用来定义布局元素的尺寸,以便在不同设备上保持一致的外观。
arrays.xml:用于存储数组资源。您可以在这个文件中定义字符串数组、整数数组等。
styles.xml:用于定义应用程序的样式和主题。这个文件包含应用程序的外观和行为的配置信息。
其他自定义文件:您可以根据需要创建其他自定义的 XML 文件,但通常应该保持与资源类型相关的文件名,并在文件中定义相应类型的资源值。
Gradle Scripts/build.gradle (Module: app) 文件:
这是应用程序的 Gradle 构建文件,用于配置和管理应用程序的构建过程。Gradle 是一种构建自动化工具,用于编译、构建和打包 Android 应用程序。
在 build.gradle (Module: app)
文件中,您可以指定应用程序的依赖项、编译版本、签名配置、构建类型(如调试或发布)等构建相关的设置。
通过编辑这个文件,您可以添加第三方库、插件,或者配置应用程序的各种构建选项,以满足特定的需求,例如添加新的功能或优化性能。
注意:你最好不要修改这个文件,如果不是非改不可的话。
XML 文件就像应用程序的"翻译书",是一种标记语言,用于存储和传输数据。它类似于应用程序中的数据存储方式。就像书中的章节和段落将信息组织成结构化的形式,XML 文件用标签(tags)将数据以结构化的方式表示出来。
比如,想象一本书,每章都有标题,每段都有内容。在 XML 文件中,您可以创建一个类似的结构,例如:
<book>
<chapter>
<title>Chapter 1</title>
<content>This is the content of Chapter 1.</content>
</chapter>
<chapter>
<title>Chapter 2</title>
<content>This is the content of Chapter 2.</content>
</chapter>
</book>
在这个例子中,<book>
是顶级标签,表示整本书。<chapter>
标签表示章节,包含了<title>
和 <content>
子标签,分别表示章节标题和内容。这种结构使得数据易于组织和理解。
简言之,XML 文件是一种用于存储和传输数据的标记语言,类似于书中的章节和段落,用于组织和表示结构化数据。
Gradle 就像应用程序的"建筑师",是一种构建自动化工具,用于编译、构建和打包应用程序。它的工作方式类似于建筑师计划和协调建筑项目。Gradle 帮助您管理和构建应用程序的不同部分,确保它们在一起协作以创建一个完整的应用程序。
比如,想象您正在建造一座房子,房子由不同的部分组成,如墙、屋顶、地板等。Gradle 就像一位建筑师,它可以:
计划项目:确定哪些部分需要建造,以及如何组装它们。
协调工作:与不同的工人(编译器、库、插件)协作,确保每个部分都按计划进行。
解决问题:如果有问题或错误,Gradle 帮助找到并修复它们,就像建筑师解决施工问题一样。
最终构建:将所有部分组合成一个完整的房子,即应用程序。
简言之,Gradle 是一种构建自动化工具,类似于应用程序的建筑师,用于计划、协调和构建应用程序的各个部分,以创建一个完整的应用程序。
它通常是一个圆形按钮,悬浮在界面的底部右侧。这是我想要的效果。
FAB 是一种常见的 UI 元素,通常用于触发应用程序中的重要操作,例如创建新内容、打开菜单或执行搜索等。
修改activity_main.xml
中的<androidx.constraintlayout.widget.ConstraintLayout
为<RelataveLayout
如下图所示:
挺简单的。
这里随便选个就行,无所谓。
OK了。
注意:activity_main.xml
中随之出现新的代码段。
右上角提示异常,不用管。
运行界面如下,你可以点这个小方框,但没啥用。
如前文所见,我们现在已实现了FAB,但点击后毫无反应,接下来我们要实现:点击FAB发生反应。
package com.example.my_notes_record;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
改成这样
package com.example.my_notes_record;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class MainActivity extends AppCompatActivity {
final String TAG ="FXS";
FloatingActionButton btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(FloatingActionButton) findViewById(R.id.floatingActionButton4);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG,"OnClick:Click");
}
});
}
}
对修改部分作简单解释如下:
final String TAG = "FXS";
TAG
,用于在日志中标记这个活动的信息。TAG 通常用于帮助您在日志中过滤和识别特定活动或类的信息。FloatingActionButton btn;
btn
的变量,类型是 FloatingActionButton
。这个变量将用于引用布局文件中的悬浮操作按钮(FloatingActionButton)。btn = (FloatingActionButton) findViewById(R.id.floatingActionButton4);
btn
变量,通过 findViewById
方法查找布局文件中的悬浮操作按钮,确保 floatingActionButton4
与activity_main.xml
中的Id对应。这样,您可以在代码中操作和控制这个按钮。可以将ID修改为其他,如fab:
android:id="@+id/fab"
MainActivity.java
中也要随之变化:
btn = (FloatingActionButton) findViewById(R.id.fab);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "OnClick: Click");
}
});
这部分代码设置了一个点击事件监听器,它会在用户点击按钮时执行。当按钮被点击时,onClick
方法内的代码将执行。具体解释如下:
btn.setOnClickListener(...)
:这是设置按钮的点击事件监听器的方法。它接受一个 View.OnClickListener
对象作为参数,用于指定按钮被点击时要执行的操作。
new View.OnClickListener()
:这是一个匿名内部类的创建,它实现了 View.OnClickListener
接口。在这个内部类中,您可以定义按钮点击时要执行的操作。
public void onClick(View view)
:这是 View.OnClickListener
接口的 onClick
方法的实现。当按钮被点击时,这个方法会被调用。
Log.d(TAG, "OnClick: Click")
:这行代码使用 Log.d
方法将一条调试日志记录到 Android 日志中。它会输出 “OnClick: Click” 文本,并使用之前定义的 TAG
来标记日志。这有助于您在开发过程中追踪按钮点击事件。
新建文件的步骤如下:
<New 1>7>
接下来需要将EditActivity.java
和edit_layout.xml
联系起来,操作过程如下:
代码自取:
//EditActivity.java
package com.example.my_notes_record;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class EditActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_layout);
}
}
最后,你需要修改AndroidManifest.xml
文件,或者说每次你新建了个布局,都需要在你的项目“说明书”(AndroidManifest.xml
)里添加上去,操作类似如下:
代码自取:
<activity android:name=".EditActivity">
</activity>
这部分挺简单的,你只需要将MainActivity.java
中的Log.d(TAG,"OnClick:Click");
(如下图所示)
换成
Intent intent = new Intent(MainActivity.this, EditActivity.class);
startActivity(intent);
就Ok了。
你运行试下,点击FAB,现在理应跳转到一个空白界面。
我这边解释一下更替的代码(不想看,跳过就好)
Intent intent = new Intent(MainActivity.this, EditActivity.class);
:首先,创建了一个名为 intent
的 Intent
对象。Intent
是 Android 中用于执行各种操作的对象,它通常用于启动活动、发送广播、执行服务等。
MainActivity.this
:这里的 MainActivity.this
表示当前活动,即您正在编写的 MainActivity
。它是一个上下文(Context)对象,用于指定从哪个活动启动 Intent
。
EditActivity.class
:这里指定了要启动的目标活动,即 EditActivity
。通过传递 EditActivity.class
,您告诉 Android 系统要启动 EditActivity
这个活动。
startActivity(intent);
:接下来,使用 startActivity
方法来启动指定的活动,也就是 EditActivity
。当用户点击悬浮操作按钮时,这行代码将触发从 MainActivity
跳转到 EditActivity
的操作。
你只需再edit_layout.xml
文件中添加如下代码:
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top">
</EditText>
如下图所示:
是不是很简答呐?
快来快来运行试试吧!
你将可以再跳转的界面里编写文档了!
这里我们需要解决这样一个问题:如何在 Android 中处理活动结果?
本来长这样:
package com.example.my_notes_record;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class MainActivity extends AppCompatActivity {
final String TAG ="FXS";
FloatingActionButton btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(FloatingActionButton) findViewById(R.id.fab);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, EditActivity.class);
startActivity(intent);
}
});
}
}
变成下面这样就OK了:
package com.example.my_notes_record;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class MainActivity extends AppCompatActivity {
final String TAG = "FXS";
FloatingActionButton btn;
// Define an ActivityResultLauncher
private ActivityResultLauncher<Intent> someActivityResultLauncher;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.fab);
// Initialize the ActivityResultLauncher
someActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK) {
Intent data = result.getData();
if (data != null) {
String edit = data.getStringExtra("input");
Log.d(TAG, edit);
}
}
}
);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, EditActivity.class);
someActivityResultLauncher.launch(intent);
}
});
}
}
好吧!改动非常大!别问我为啥就是个接受结果的逻辑,咋整这么复杂。我也想知道(┬┬﹏┬┬)
所以如果你看到现在还有耐心的话,请听我慢慢讲来:
// Define an ActivityResultLauncher
private ActivityResultLauncher<Intent> someActivityResultLauncher;
ActivityResultLauncher
对象,名为 someActivityResultLauncher
。ActivityResultLauncher
是一个用于启动活动并获取结果的新方式。在这里,我们声明了它,并指定它将接受一个 Intent
对象作为输入。// Initialize the ActivityResultLauncher
someActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK) {
Intent data = result.getData();
if (data != null) {
String edit = data.getStringExtra("input");
Log.d(TAG, edit);
}
}
}
);
在 onCreate
方法中,我们初始化了 someActivityResultLauncher
。这是一个两步过程:
首先,我们调用 registerForActivityResult
方法来初始化 someActivityResultLauncher
。这个方法接受两个参数:第一个参数是 ActivityResultContracts.StartActivityForResult()
,它告诉系统我们要启动一个活动并获取结果。第二个参数是一个回调函数,当活动返回结果时,将执行这个回调。
在回调函数中,我们检查 result.getResultCode()
,以确保活动返回的结果是 RESULT_OK
,这通常表示操作成功。然后,我们检查 result.getData()
是否为 null,以确保有数据返回。如果有数据返回,我们从返回的 Intent
中获取额外的数据,例如用户输入的文本,并记录到日志中。
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, EditActivity.class);
someActivityResultLauncher.launch(intent);
}
});
someActivityResultLauncher.launch(intent)
来启动 EditActivity
。这个方法会启动活动并在活动完成后触发回调函数,从而处理活动返回的结果。原来长这样:
package com.example.my_notes_record;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class EditActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_layout);
}
}
变成这样:
package com.example.my_notes_record;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import java.security.Key;
public class EditActivity extends AppCompatActivity{
EditText et;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_layout);
et=findViewById(R.id.et);
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_HOME){
return true;
}else if(keyCode == KeyEvent.KEYCODE_BACK){
Intent intent = new Intent();
intent.putExtra("input",et.getText().toString());
setResult(RESULT_OK,intent);
finish();
return true;
}
return super.onKeyDown(keyCode,event);
}
}
作简单解释如下:
这次的修改是在 EditActivity
添加了一些新的功能:
EditText 控件的引用:首先,在 onCreate
方法中,您通过 et=findViewById(R.id.et);
获取了一个 EditText
控件的引用,其中 R.id.et
是布局文件 edit_layout.xml
中的一个 EditText
控件的标识符。
按键事件监听:您还重写了 onKeyDown
方法来处理按键事件。在这个方法中,您检查用户按下的按键码(keyCode
)是否是 KeyEvent.KEYCODE_HOME
或 KeyEvent.KEYCODE_BACK
。
如果用户按下了 HOME 键(KeyEvent.KEYCODE_HOME
),则返回 true
,表示您处理了此按键事件。这样可以阻止用户按下 HOME 键时退出应用程序。
如果用户按下了返回键(KeyEvent.KEYCODE_BACK
),则执行以下操作:
Intent
对象。EditText
中输入的文本(et.getText().toString()
)放入 Intent
中,以便返回到 MainActivity
。setResult
方法设置结果为 RESULT_OK
,表示操作成功。finish()
方法关闭当前的 EditActivity
,返回到 MainActivity
。这个修改的目的是在用户编辑文本后,按下返回键时将编辑的文本数据传递回到 MainActivity
,以便在 MainActivity
中处理和显示这些数据。
接下来你可以运行试下,就像开篇时演示时那样!
好的,本文结束。希望你在本文中找到了有关Android应用开发的有用信息,不要害怕尝试新的东西,愿你编码愉快,创造出出色的应用,做一名优秀的开发者!如果你有任何问题,不妨向世界求助,因为谷歌是你最好的朋友,至少在编码的世界里是这样的。祝编码愉快,愿你的代码永远不崩溃!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。