Android practice: Food Project (II)

Time:2022-6-2

Create navigation and bottom menu bar

Create fragments of several pages and add navigation

For the creation of fragments, please refer tohttps://www.jianshu.com/p/5974e52a024d
Add marked fragments temporarily, and refer to others later

Android practice: Food Project (II)

image.png

Change the constraints of XML files corresponding to all fragments to constraintlayout
And all fragments are changed into binding to access the control

Android practice: Food Project (II)

Template

Create a navigation in res and add the newly created fragment to the navigation

Android practice: Food Project (II)

image.png

Remove actionbar
Actionbar, that is, the navigation information of the header, is not used in this project
res -> themes -> themes. XML (change both)

Android practice: Food Project (II)

image.png

In activity_ main. Add two controls to XML
Constraint layout at the same time

Android practice: Food Project (II)

image.png

Add menu

Create a menu the same way you create a navigation

Android practice: Food Project (II)

menu

ID is the ID corresponding to the fragment. Each menu button is bound with a corresponding fragment so that page switching can be completed when clicked
Icon is a button icon, which can be added to drawable by yourself. If you are too lazy to design pictures, you can right-click to add vector asset in drawable to add picture resources provided by the system
Showasaction shows when the bottom menu bar will be displayed: the editor originally chose always, but the system recommends using ifroom

Here, let’s explain the three different statuses of shoasaction:
Always: indicates that it is always displayed in the container (the container here refers to the bottomnavigationbar)
Ifroom: indicates that it is displayed in the container if the screen is large enough, and in the menu if it is not large enough
Never: indicates that it is always displayed in the menu
As for the specific effect of each, you will know after trying

Icontint set default color

Android practice: Food Project (II)

Detailed introduction
<?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>

Setting button click status color change
Set the menu property of bottomnavigaitonview, and set the bottom_ Menu set to menu.

Android practice: Food Project (II)

image.png

Create a color file and an item in Res_ 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 interface setup

Android practice: Food Project (II)

image.png

Shapeableimageview: set the circular pattern through shapeappearanceoverlay

Android practice: Food Project (II)

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>

Background color setting at the top of mobile screen
In order to make the background color of the image we set consistent with the system default top color, we need to Change color in XML

Android practice: Food Project (II)

statusBarColor

Search bar design

Android practice: Food Project (II)

xml

In recipefrragment
Note: this cannot be used in the context of the fragment, but requirecontext is required

private fun initRecyclerView(){
        //Recyclerview for configuration type selection
        binding.typeRecyclerView.layoutManager = LinearLayoutManager(requireContext(),RecyclerView.HORIZONTAL,false)
        binding.typeRecyclerView.adapter = typeAdapter
        //Handling callback events
        typeAdapter.callBack= {current, last ->
            val currentHolder = binding.typeRecyclerView.findViewHolderForAdapterPosition(current) as TypeAdapter.MyViewHolder
            val lastHolder = binding.typeRecyclerView.findViewHolderForAdapterPosition(last)
            //Select current
            currentHolder.changeSelectedStatus(true)
            //Cancel the previously selected
            if (lastHolder != null){
                val lastTypeHolder = lastHolder as TypeAdapter.MyViewHolder
                lastTypeHolder.changeSelectedStatus(false)
            }else{
                //Refresh the last selected item
                typeAdapter.notifyItemChanged(last)
            }
            //Get data
            fetchData(typeAdapter.typeList[current])
        }

    }

Layout corresponding to adapter

Android practice: Food Project (II)

image.png

In typeadapter

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 for event callback
    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) {
        //Data callback
        var callBack:((Int)->Unit)?=null
        companion object{
            fun from(parent: ViewGroup): MyViewHolder {
                //Create viewholder
                val inflater = LayoutInflater.from(parent.context)
                return MyViewHolder(ItemTypeBinding.inflate(inflater))
            }
        }
        //Binding data
        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)
        //Handle callback events after clicking
        holder.callBack = {
            //Is the point the same
            if (it!=lastSelectedPosition){
                callBack?.let { call ->
                    call(it,lastSelectedPosition)
                    //Record the currently selected index
                    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
    }

}

See the following chapter for the detailed implementation analysis of the search bar

Unfinished to be continued
Project complete code