小白快速入门安卓布局
下面将从构建新项目开始,逐步实现一些小功能,快速地认识一些基本的操作。于此同时,我也会和angular的知识进行对比叙述。 打开android studio 左上角 File -> new 记得将左上角的模式调成project模式 从上到下是图片资源的存放文件夹,可以看到很多drawable前缀的文件夹,代表着不同分辨率下用到的图片 接下来创建一个文件夹menu,注意这里比较特殊,这里需要创建特定的文件夹,否则无法识别到到其他文件中, 且menu,item控件都会识别不了。 这里就可以进一步探索,动态渲染的机制,在angular中我们经常在模板中使用@for去循环构造模板,在android中怎么实现呢。 在layout中创建子项目的模板文件item_horizontal.xml 接下来我们创建适配器,用于处理循环渲染的步骤。 然后去使用了该循环的xml文件,对应的c层注册该适配器 我们点击导航栏应该让页面作出一些变化,但是导航栏不能整体变化,我们就会想到angular的组件思想。那么,在android中如何实现呢?我们接下来会使用到Fragment。 同理控制器中的逻辑也需要迁移过去 对于MainActivity我们需要让他去选择需要显示的Fragment 接下来点击运行,点击导航栏就完成页面跳转效果了。背景
1. 本学期接触到了安卓开发的课程,预计使用一个半月的时间带领剩下3个没有开发经验的同学开发好一个像样的app
2. 自己本人也有了解的兴趣。概述
构建新项目
红色框布局主要是 XML+setContentView
蓝色框是 Jetpack Compose (近几年google推荐的)
本文章介绍的是XML+setContentView项目,选型原因主要是社区完善,且布局设计对新手友好,上手较快。文件结构
在这个java下的包是我们的控制类
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
// 绑定v层
setContentView(R.layout.activity_main)
}
}
layout文件夹放着页面和组件文件,menu文件夹放着导航的项目(接下来会重点介绍)
mipmap文件夹与图片资源同理,不过存放的是app的图标
values文件夹放的是一些常用变量
AndroidManifest.xml是注册页面的地方
渲染流程

AndroidManifest.xml
MainActivity控制类,注意这里引入一个新概念,对于src下的文件名也可以使用R去访问,R也可以去访问values文件夹中的变量。
有一个很方便的布局,在布局标签上声明androidx.constraintlayout.widget.ConstraintLayout就可以使用图形界面去快速的布局
这里有个学习链接(图形化布局)
实现导入组件库

找到这个文件,添加依赖
点击File -> Sync Project With Gradle Files
在官网中,复制代码底部导航栏指导
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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="421dp"
android:layout_height="93dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_navigation_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
选择type为menu
接下来将内容填进去,发现爆红了,之前我们说过了可以用R去访问资源,那么在v层中就是使用@去访问静态资源。当然动态生成的就在c层进行绑定。
填加资源
我们可以使用官方的图标


最后静态导航栏的实现效果
实现一个可滑动的横向列表
在activity_main.xml中加入这段代码 <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewHorizontal"
android:layout_width="426dp"
android:layout_height="75dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.533"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/textView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="100dp"
android:gravity="center"
android:textSize="16sp"
android:layout_margin="8dp"/>import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication.R
class HorizontalAdapter(private val dataList: List<String>) :
RecyclerView.Adapter<HorizontalAdapter.ViewHolder>() {
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textView: TextView = itemView.findViewById(itemView.id)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// LayoutInflater.from(parent.context)将转化xml为对象
// inflat函数开始进行创建循环中的子项目, 第一个参数获取子项目的样式,第二个参数获取父盒子的样式,第三个参数表示是否构造完一个个就塞到父盒子里
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_horizontal, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = dataList[position]
holder.textView.text = item
// 可以设置点击事件
holder.itemView.setOnClickListener {
// 处理点击
}
}
override fun getItemCount() = dataList.size
}
效果,可滑动
实现页面跳转
创建Fragment

同理创建homeFragment
接下来将我们之前写在activity_main.xml的部分控件放到homeFragment.xml中<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".HomeFragment">
<TextView
android:id="@+id/textView"
android:layout_width="209dp"
android:layout_height="52dp"
android:layout_marginBottom="84dp"
android:text="Hello World!"
app:layout_constraintBottom_toTopOf="@+id/btnMaterial"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.549"
app:layout_constraintStart_toStartOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewHorizontal"
android:layout_width="426dp"
android:layout_height="75dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.533"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnMaterial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="120dp"
android:text="我是一个 Material 按钮"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.612" />
</androidx.constraintlayout.widget.ConstraintLayout>package com.example.myapplication
import HorizontalAdapter
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// 1. 加载布局文件
val view = inflater.inflate(R.layout.fragment_home, container, false)
// 2. 从当前 Fragment 的视图中查找 RecyclerView
val recyclerView: RecyclerView = view.findViewById(R.id.recyclerViewHorizontal)
// 3. 设置水平布局管理器
val layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
recyclerView.layoutManager = layoutManager
// 4. 准备数据
val data = mutableListOf<String>()
for (i in 1..20) {
data.add("Item $i")
}
// 5. 设置适配器(确保 HorizontalAdapter 已定义)
val adapter = HorizontalAdapter(data)
recyclerView.adapter = adapter
// 6. 返回填充好的视图
return view
}
}package com.example.myapplication
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.google.android.material.bottomnavigation.BottomNavigationView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_navigation)
// 设置默认显示的 Fragment(例如首页)
if (savedInstanceState == null) {
replaceFragment(HomeFragment())
}
// 设置导航项选中监听
bottomNav.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.page_1 -> { // 注意这里的 ID 必须与菜单文件中一致
replaceFragment(HomeFragment())
true
}
R.id.page_2 -> {
replaceFragment(PersonalFragment())
true
}
else -> false
}
}
}
// 替换 Fragment 的辅助方法
private fun replaceFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit()
}
}表单提交
表格
交验器
状态管理
自定义样式
总结
以上写法耦合性太强