Recently, there are many nested controls in the project, and I have encountered many problems. I solved them yesterday and quickly recorded them
The scene is ViewPager2 nested NestedScrollView nested RecyclerView waterfall stream
Effect:
I can’t. It’s too compressed. It’s ok
The main problems are as follows:
- NestedScrollView/ScrollView nested RecyclerView conflict, do not scroll, display incomplete, or do not display problems
- NestedScrollView/ScrollView nested RecyclerView Waterfall flow double sliding problem
- Open the page after the location of RecyclerView problem
I have tried NestedScrollView and ScrollView, and the effect is the same
Problem 1: NestedScrollView/ScrollView nested RecyclerView conflict, do not scroll, display incomplete, or do not display problems
About this problem, it is the most important one. CSDN says a lot that layout_height match_parent should be changed to WRap_content. In fact, this has no impact, because the essence of the problem is that we need to give a fixed height of RecyclerView to solve it.
If you set it to match_parent, it will not show up, so we just need to set the RecyclerView to a fixed height. Or dynamically calculate the control height, and then set, you can solve the problem.
We can set the layout_height of RecyclerView in XML to a fixed height, 1000DP or something like that. But we can’t control the height of the waterfall. However, in real development we are not sure how high the data needs to be loaded, so write dead height may not be a good idea. So the layout code is not posted
Another way of thinking is to dynamically calculate the required height, and then set it to him.
I’m dealing with it based on the length of waterfall flow data. The height can be calculated according to the specific service.
/ / computing needs highly ViewGroup. LayoutParams LayoutParams. = menuHomeBinding rvWaterFallsFlow. GetLayoutParams (); int height = 0; for (int i = 0; i < waterFallsFlowBeanArrayList.size(); i++) { if (i % 2 == 0) { height += 400; } else if (i % 3 == 0) { height += 360; } else { height += 440; }} / / as long as the business process after the height of the assigned to layoutParams. The height is ok layoutParams. Height = height - waterFallsFlowBeanArrayList. Size (* 100); menuHomeBinding.rvWaterFallsFlow.setLayoutParams(layoutParams);Copy the code
I also thought about calculating the height in Adapter and then getting the post-processing, but I tried it, and it always got 0. If you have any ideas, please let me know.
Problem two: NestedScrollView/ScrollView nested RecyclerView waterfall flow double sliding problem
After the normal display, there will be NestedScrollView/ScrollView sliding, inside RecyclerView can also slide the effect.
So what we need to do here is not let the RecyclerView slide inside, but let it slide along with NestedScrollView/ScrollView. Here, there is a property in the official API that can help us solve this problem. Is this setNestedScrollingEnabled, this is to start the nested scroll switch. The default is true.
Of course, it can also be set in the layout file, if it is set in the layout file, it is set in RecyclerView. I’m setting it up in code here.
menuHomeBinding.rvWaterFallsFlow.setNestedScrollingEnabled(false);
Copy the code
Problem three: After opening the page, locate the RecyclerView problem
Based on the above, the effect can be displayed normally, but after opening the App, it will automatically locate to the RecyclerView position.
This is because RecyclerView automatically gets focus by default, so we need to take care of that. There are two ways
In XML, when you switch to another page and come back, the focus is always at the top. If set in code, when you switch pages and come back, the location will stay where you were before browsing.
The following is a specific solution.
-
XML way
Add a property to get focus to the first child control of NestedScrollView/ScrollView
android:focusable="true"
android:focusableInTouchMode="true"
Copy the code
NestedScrollView and ScrollView are both allowed to have only one child control. The first child control is the first child control in the unique child control.
<androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <! - the first child controls - > < androidx. Viewpager. Widget. The viewpager android: id = "@ + id/vp_home_menu_banner" android:layout_width="match_parent" android:layout_height="160dp" android:focusable="true" android:focusableInTouchMode="true" android:layout_marginStart="10dp"/>Copy the code
-
In-code processing
The second is to do it in code. The way I did it, it was very simple.
Since RecyclerView automatically gets focus by default, then we just need to set the code to not let it get focus by default.
menuHomeBinding.rvWaterFallsFlow.setFocusable(false);
Copy the code
conclusion
Basically, the properties that we use are
menuHomeBinding.rvWaterFallsFlow.setHasFixedSize(true);
menuHomeBinding.rvWaterFallsFlow.setNestedScrollingEnabled(false);
menuHomeBinding.rvWaterFallsFlow.setFocusable(false);
Copy the code
Important points: determine the height of RecyclerView
Please ignore the useless code, just look at the outermost NestedScrollView and the bottom RecyclerView OK
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Banner -->
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp_home_menu_banner"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_marginStart="10dp"/>
<!-- 功能菜单 -->
<LinearLayout
android:id="@+id/ll_home_menu"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/ll_home_menu_reservation"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:background="@drawable/style_constraintlayout_purple_gradient_bg"
android:gravity="center"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="@+id/cv_menu_home_reservation"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginHorizontal="6dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="60dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerInside"
android:src="@drawable/home_menu_reservation" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="4dp"
android:gravity="center"
android:text="@string/homeMenuReservation"
android:textColor="@color/white" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_home_menu_group"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:background="@drawable/style_constraintlayout_blue_gradient_bg"
android:gravity="center"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="@+id/cv_menu_home_group"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginHorizontal="6dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="60dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerInside"
android:src="@drawable/home_menu_group" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="4dp"
android:gravity="center"
android:text="@string/homeMenuGroup"
android:textColor="@color/white" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_home_menu_unpack"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:background="@drawable/style_constraintlayout_orange_gradient_bg"
android:gravity="center"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="@+id/cv_menu_home_unpack"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginHorizontal="6dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="60dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerInside"
android:src="@drawable/home_menu_unpack" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="4dp"
android:gravity="center"
android:text="@string/homeMenuUnpack"
android:textColor="@color/white" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_home_menu_game"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:background="@drawable/style_constraintlayout_red_gradient_bg"
android:gravity="center"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="@+id/cv_menu_home_game"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginHorizontal="6dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="60dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerInside"
android:src="@drawable/home_menu_game" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="4dp"
android:gravity="center"
android:text="@string/homeMenuGame"
android:textColor="@color/white" />
</LinearLayout>
<TextView
android:id="@+id/tv_home_menu_gourmet"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawableTop="@mipmap/ic_home_menu_gourmet"
android:drawablePadding="3dp"
android:gravity="center"
android:text="@string/homeMenuGourmet"
android:visibility="gone" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/lightGray"
android:nestedScrollingEnabled="false"
android:orientation="vertical">
<!-- 秒杀 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_home_spike"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp"
android:background="@drawable/style_linearlayout_round">
<TextView
android:id="@+id/tv_home_spike"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@drawable/style_textview_horizontal_gradient_round_top"
android:gravity="start|center_vertical"
android:paddingStart="16dp"
android:paddingEnd="10dp"
android:text="@string/homeSpike"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/cv_home_spike_img"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginStart="20dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/ll_home_spike"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_home_spike">
<ImageView
android:layout_width="match_parent"
android:layout_height="80dp"
android:src="@drawable/test_1" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/ll_home_spike"
android:layout_width="0dp"
android:layout_height="60dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@+id/cv_home_spike_img"
app:layout_constraintTop_toBottomOf="@id/tv_home_spike">
<TextView
android:layout_width="match_parent"
android:layout_height="30dp"
android:gravity="start|center_vertical"
android:paddingStart="20dp"
android:text="00000000"
android:textColor="@color/deepTextColor"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="30dp"
android:gravity="start|center_vertical"
android:paddingStart="20dp"
android:text="111111111111" />
</LinearLayout>
<TextView
android:id="@+id/tv_home_spike_discount_price"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:gravity="center"
android:paddingStart="20dp"
android:text="¥99.00"
android:textColor="@color/crimson"
app:layout_constraintStart_toEndOf="@id/cv_home_spike_img"
app:layout_constraintTop_toBottomOf="@id/ll_home_spike" />
<TextView
android:id="@+id/tv_home_spike_price"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:gravity="start|center_vertical"
android:paddingStart="20dp"
android:text="¥199.00"
android:textColor="@color/grey"
app:layout_constraintStart_toEndOf="@id/tv_home_spike_discount_price"
app:layout_constraintTop_toBottomOf="@id/ll_home_spike" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 优惠券 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_home_coupon"
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp"
android:background="@drawable/style_linearlayout_round">
<TextView
android:id="@+id/tv_menu_home_coupon_list"
android:layout_width="match_parent"
android:layout_height="35dp"
android:background="@drawable/style_textview_horizontal_gradient_round_top"
android:gravity="start|center_vertical"
android:paddingStart="16dp"
android:text="@string/menuHomeCouponList"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_menu_home_coupon_seller1"
android:layout_width="0dp"
android:layout_height="30dp"
android:gravity="center"
android:text="每满1000减100元"
android:textColor="@color/crimson"
app:layout_constraintBottom_toTopOf="@id/tv_menu_home_description1"
app:layout_constraintEnd_toStartOf="@id/tv_menu_home_coupon_seller2"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_menu_home_coupon_list" />
<TextView
android:id="@+id/tv_menu_home_description1"
android:layout_width="0dp"
android:layout_height="30dp"
android:gravity="center"
android:text="仅可购买部分品类商品"
app:layout_constraintEnd_toStartOf="@id/tv_menu_home_description2"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_menu_home_coupon_seller1" />
<Button
android:id="@+id/btn_menu_home_coupon1"
android:layout_width="100dp"
android:layout_height="28dp"
android:layout_marginStart="40dp"
android:background="@drawable/style_coupon_button_round"
android:text="@string/menuHomeCouponReceive"
android:textColor="@color/crimson"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_menu_home_coupon_dividing_line"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_menu_home_description1" />
<TextView
android:id="@+id/tv_menu_home_coupon_dividing_line"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginHorizontal="-40dp"
android:background="@drawable/style_dividing_line_vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_menu_home_coupon_seller2"
app:layout_constraintStart_toEndOf="@id/tv_menu_home_coupon_seller1"
app:layout_constraintTop_toBottomOf="@id/tv_menu_home_coupon_list" />
<TextView
android:id="@+id/tv_menu_home_coupon_seller2"
android:layout_width="0dp"
android:layout_height="30dp"
android:gravity="center"
android:text="每满1000减100元"
android:textColor="@color/crimson"
app:layout_constraintBottom_toTopOf="@id/tv_menu_home_description2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/tv_menu_home_coupon_seller1"
app:layout_constraintTop_toBottomOf="@id/tv_menu_home_coupon_list" />
<TextView
android:id="@+id/tv_menu_home_description2"
android:layout_width="0dp"
android:layout_height="30dp"
android:gravity="center"
android:text="仅可购买部分品类商品"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/tv_menu_home_description1"
app:layout_constraintTop_toBottomOf="@id/tv_menu_home_coupon_seller2" />
<Button
android:id="@+id/btn_menu_home_coupon2"
android:layout_width="100dp"
android:layout_height="28dp"
android:layout_marginEnd="40dp"
android:background="@drawable/style_coupon_button_round"
android:text="@string/menuHomeCouponReceive"
android:textColor="@color/crimson"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_menu_home_coupon_dividing_line"
app:layout_constraintTop_toBottomOf="@id/tv_menu_home_description2" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 瀑布流 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_water_falls_flow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</layout>
Copy the code
Fragment: Also ignore useless logic
package com.qingnuo.yami.view.home; import android.content.Context; import android.content.Intent; import android.database.Observable; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.databinding.DataBindingUtil; import androidx.databinding.ObservableField; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; import com.youth.banner.adapter.BannerImageAdapter; import com.youth.banner.holder.BannerImageHolder; import com.youth.banner.indicator.CircleIndicator; import java.util.ArrayList; import java.util.List; Public Class Home Max extends Fragment implements view. OnClickListener {private static final String TAG = "HomeMenuFragment"; private FragmentMenuHomeBinding menuHomeBinding; private Context mContext; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { menuHomeBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_menu_home, container, false); mContext = getContext(); initView(); return menuHomeBinding.getRoot(); } private void initView () {/ / set the Adapter HomeWaterFallsFlowAdapter waterFallsFlowAdapter = new HomeWaterFallsFlowAdapter(mContext); waterFallsFlowAdapter.setList(waterFallsFlowBeanArrayList); menuHomeBinding.rvWaterFallsFlow.setAdapter(waterFallsFlowAdapter); / / computing needs highly ViewGroup. LayoutParams LayoutParams. = menuHomeBinding rvWaterFallsFlow. GetLayoutParams (); int height = 0; for (int i = 0; i < waterFallsFlowBeanArrayList.size(); i++) { if (i % 2 == 0) { height += 400; } else if (i % 3 == 0) { height += 360; } else { height += 440; } } layoutParams.height = height - waterFallsFlowBeanArrayList.size() * 100; menuHomeBinding.rvWaterFallsFlow.setLayoutParams(layoutParams); menuHomeBinding.rvWaterFallsFlow.setHasFixedSize(true); menuHomeBinding.rvWaterFallsFlow.setNestedScrollingEnabled(false); menuHomeBinding.rvWaterFallsFlow.setFocusable(false); }}Copy the code
NestedScrollView nesting RecyclerView can not normally display NestedScrollView to solve the use of nested display is not fully nested do not display the problem