美文网首页无名之辈的Android之路
Android 实战:美食项目(二)

Android 实战:美食项目(二)

作者: 搬码人 | 来源:发表于2021-09-09 20:01 被阅读0次

    创建导航和底部菜单栏

    创建几个页面的fragment和添加navigation

    有关fragment的创建可参考https://www.jianshu.com/p/5974e52a024d
    暂时添加标记的fragment,其他的后边再提及

    image.png
    将所有fragment对应的xml文件的约束改为ConstraintLayout
    并且将所有的fragment都换成binding的形式访问控件
    模板

    在res中创建navigation并且将刚创建的fragment添加到navigation中


    image.png

    去掉ActionBar
    本项目中用不到ActionBar,也就是头部的导航信息
    res -> themes -> themes.xml(两个都改)

    image.png

    在activity_main.xml中添加两个控件
    同时进行约束布局

    image.png

    添加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上。

    image.png
    在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.png

    ShapeableImageView:通过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中更改颜色

    statusBarColor

    搜索栏设计

    xml

    RecipeFragment中
    注:在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
        }
    
    }
    

    关于搜索栏的详细实现分析见下章

    未完待续
    项目完整代码

    相关文章

      网友评论

        本文标题:Android 实战:美食项目(二)

        本文链接:https://www.haomeiwen.com/subject/lhwiwltx.html