创建导航和底部菜单栏
创建几个页面的fragment和添加navigation
有关fragment的创建可参考https://www.jianshu.com/p/5974e52a024d
暂时添加标记的fragment,其他的后边再提及
将所有fragment对应的xml文件的约束改为ConstraintLayout
并且将所有的fragment都换成binding的形式访问控件
模板
在res中创建navigation并且将刚创建的fragment添加到navigation中
image.png
去掉ActionBar
本项目中用不到ActionBar,也就是头部的导航信息
res -> themes -> themes.xml(两个都改)
在activity_main.xml中添加两个控件
同时进行约束布局
添加menu菜单
使用同创建navigation一样的方式创建menu
menu
id就是fragment对应的id,每个菜单按钮绑定一个对应的fragment使点击时能完成页面切换
icon为按钮图标,可以自己添加到drawable中,如果懒得设计图片的话可以在drawable右键添加Vector Asset添加系统提供的图片资源
showAsAction为底部菜单栏什么时候展示:小编本来是选择always的,不过系统建议使用ifRoom
这里小编来解释一下shoAsAction的三种不同状态:
always:表示一直显示在容器中(这里的容器指的是BottomNavigationBar)
ifRoom:表示在屏幕足够大的情况下显示在容器中,不够的话显示在菜单中
never:表示永远显示在菜单中
至于每种的效果具体如何,大家试过就知道
iconTint设置默认颜色
详细介绍
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/recipeFragment"
android:icon="@drawable/ic_book"
android:title="Recipes"
app:showAsAction="ifRoom"
android:iconTint="#7C7B7E"
tools:targetApi="o" />
<item
android:id="@+id/favoriteFragment"
android:icon="@drawable/ic_star"
android:title="Favorite"
app:showAsAction="ifRoom"
android:iconTint="#7C7B7E"
tools:targetApi="o"/>
<item
android:id="@+id/otherFragment"
android:icon="@drawable/ic_other"
android:title="Other"
app:showAsAction="ifRoom"
android:iconTint="#7C7B7E"
tools:targetApi="o"/>
</menu>
设置按钮点击状态颜色改变
设置BottomNavigaitonView的menu属性,将刚创建的bottom_menu设置到menu上。
在res中创建color文件并且创建item_color.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#F5FC" android:state_checked="true"/>
<item android:color="#7C7b7E" android:state_checked="false"/>
</selector>
fragment_recipe.xml界面搭建
image.pngShapeableImageView:通过shapeAppearanceOverlay设置圆形图案
image.png
<?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/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.recipe.RecipeFragment">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/main_bg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="Welcome to Food App"
android:textColor="@color/white"
android:textSize="26sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Ready to cook launch?"
app:layout_constraintStart_toStartOf="@+id/textView2"
app:layout_constraintTop_toBottomOf="@+id/textView2"
android:textStyle="bold"
android:textColor="#817F7C"
android:textSize="20sp"/>
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/shapeableImageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/textView2"
app:shapeAppearanceOverlay="@style/roundedCornerImageStyle"
app:srcCompat="@drawable/myhead" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:src="@drawable/top"
app:layout_constraintEnd_toEndOf="@+id/shapeableImageView"
app:layout_constraintStart_toStartOf="@+id/textView3"
app:layout_constraintTop_toBottomOf="@+id/textView3"
android:scaleType="centerCrop"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/typeRecyclerView"
android:layout_width="383dp"
android:layout_height="50dp"
android:layout_marginTop="30dp"
app:layout_constraintEnd_toEndOf="@+id/imageView2"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/imageView2"
app:layout_constraintTop_toBottomOf="@+id/imageView2" />
<com.todkars.shimmer.ShimmerRecyclerView
android:id="@+id/foodRecyclerView"
android:layout_width="0dp"
android:layout_height="272dp"
android:layout_marginTop="15dp"
app:shimmer_recycler_layout="@layout/food_item_shimmer_layout"
app:shimmer_recycler_item_count="4"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="@+id/typeRecyclerView"
app:layout_constraintStart_toStartOf="@+id/typeRecyclerView"
app:layout_constraintTop_toBottomOf="@+id/typeRecyclerView"
app:layout_constraintVertical_bias="0.355" />
</androidx.constraintlayout.widget.ConstraintLayout>
手机屏幕顶部背景色设置
为了使我们设置的图片的背景色和系统默认的顶部颜色不违和,我们需要在theme.xml中更改颜色
搜索栏设计
xmlRecipeFragment中
注:在fragment中context不能使用this,而需要使用requireContext
private fun initRecyclerView(){
//配置类型选择的RecyclerView
binding.typeRecyclerView.layoutManager = LinearLayoutManager(requireContext(),RecyclerView.HORIZONTAL,false)
binding.typeRecyclerView.adapter = typeAdapter
//处理回调事件
typeAdapter.callBack= {current, last ->
val currentHolder = binding.typeRecyclerView.findViewHolderForAdapterPosition(current) as TypeAdapter.MyViewHolder
val lastHolder = binding.typeRecyclerView.findViewHolderForAdapterPosition(last)
//选中当前
currentHolder.changeSelectedStatus(true)
//取消之前选中的
if (lastHolder != null){
val lastTypeHolder = lastHolder as TypeAdapter.MyViewHolder
lastTypeHolder.changeSelectedStatus(false)
}else{
//重新把上一次选中的item刷新
typeAdapter.notifyItemChanged(last)
}
//获取数据
fetchData(typeAdapter.typeList[current])
}
}
适配器对应的布局
image.png
TypeAdaper中
package com.example.foodresp.fragment.recipe.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.foodresp.databinding.ItemTypeBinding
/**
*@Description
*@Author PC
*@QQ 1578684787
*/
class TypeAdapter:RecyclerView.Adapter<TypeAdapter.MyViewHolder>() {
//事件回调的lambda
var callBack:((current:Int,last:Int)->Unit)?=null
val typeList = listOf("main course","side dish","dessert","appetizer","salad","bread",
"breakfast","beverage","sauce","marinade","finger food","snack","drink")
private var lastSelectedPosition = 0
class MyViewHolder(private val binding:ItemTypeBinding):RecyclerView.ViewHolder(binding.root) {
//数据回调
var callBack:((Int)->Unit)?=null
companion object{
fun from(parent: ViewGroup): MyViewHolder {
//创建ViewHolder
val inflater = LayoutInflater.from(parent.context)
return MyViewHolder(ItemTypeBinding.inflate(inflater))
}
}
//绑定数据
fun bind(type:String,position: Int){
binding.titleTextView.text = type
binding.titleTextView.setOnClickListener {
callBack?.let {it(position) }
changeSelectedStatus(true)
}
}
fun changeSelectedStatus(status:Boolean){
binding.titleTextView.isSelected = status
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val holder = MyViewHolder.from(parent)
//处理点击之后的回调事件
holder.callBack = {
//点的是不是同一个
if (it!=lastSelectedPosition){
callBack?.let { call ->
call(it,lastSelectedPosition)
//记录当前被选中的索引
lastSelectedPosition = it
}
}
}
return holder
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(typeList[position],position)
if (position == lastSelectedPosition){
holder.changeSelectedStatus(true)
}else{
holder.changeSelectedStatus(false)
}
}
override fun getItemCount(): Int {
return typeList.size
}
}
关于搜索栏的详细实现分析见下章
网友评论