Хоризонтален и вертикален RecyclerView под един и същ свитък

Трябва да направя нещо като Instagram. Имам хоризонтален RecyclerView за истории и по-долу вертикален RecyclerView за емисии. Искам да постигна същото поведение при превъртане (историите трябва да вървят с емисия при превъртане, а не да остават отгоре, както е фиксирано). Единственото решение, което намерих, е NestedScrollView, но то прави изключително лошо представяне за RecyclerViews, екранът ми замръзва почти завинаги. Опитах много трикове, намерени тук, като nestedScrollEnabled, autoLayoutMeasure и т.н., но нищо не работи. Благодаря.


person Ciobanu Razvan    schedule 25.07.2018    source източник
comment
защо това трябва да реши проблема ми?   -  person Ciobanu Razvan    schedule 25.07.2018
comment
Оформлението на координатора е най-добро за поддръжка на множество събития за превъртане. можете да използвате вашето поведение при превъртане cutsom с него   -  person Saurabh Bhandari    schedule 25.07.2018


Отговори (2)


Съжалявам, ако това обяснение е твърде абстрактно. Уведомете ме, ако имате нужда да бъда по-ясен.

public class VerticalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

private static final int TYPE_HEADER = 0;
private static final int TYPE_POST = 1;

List<Post> posts;
List<FeedItems> feedItems; //this array is going to populate the horizontal recycler view. Notice that is passed it on the adapter constructor

public VerticalAdapter(List<Post> posts,List<FeedItems> feedItems) {
    this.posts = posts;
    this.feedItems = feedItems;
}

public void notifyFeedChanged(List<FeedItems> newFeedItems){
    this.feedItems.clear();
    this.feedItems = newFeedItems; //set the new feed items in the array
    notifyItemChanged(0); //tell the main recycler view "Hey, update your first position". This will cause the onBindViewHolder to be called again an thus, the new items will be set into the horizontal recycler view
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    if (viewType == TYPE_HEADER)
        return new HeaderViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.your_header_layout, false));
    else if (viewType == TYPE_POST)
        return new PostViewHolder (LayoutInflater.from(parent.getContext()).inflate(R.layout.your_post_layout, false));

    throw new RuntimeException("Don't know this type");
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {


    if (holder instanceof HeaderViewHolder){
        //set adapter for the horizontal recycler view
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(((HeaderViewHolder) holder).recyclerView.getContext(),LinearLayoutManager.HORIZONTAL, false)
        ((HeaderViewHolder) holder).recyclerView.setLayoutManager(linearLayoutManager);

        if (((HeaderViewHolder) holder).recyclerView.getAdapter() == null){ //only create the adapter the first time. the following times update the values
            AnotherAdaterYouNeedToCreateForTheHorizontalRecyclerView adapter = new AnotherAdaterYouNeedToCreateForTheHorizontalRecyclerView(feedItems);
            ((HeaderViewHolder) holder).recyclerView.setAdapter(adapter);
        }else {
            ((HeaderViewHolder) holder).recyclerView.getAdapter().notifyDataSetChanged();
        }

    }else if (holder instanceof PostViewHolder){
        //just do the normal post binding
    }
}

@Override
public int getItemCount() {
    return posts.size() + 1; // +1 because of the header
}

@Override
public int getItemViewType(int position) {
    return position == 0 ? TYPE_HEADER : TYPE_POST;
}

private class HeaderViewHolder extends RecyclerView.ViewHolder{

    RecyclerView recyclerView;

    public HeaderViewHolder(View itemView) {
        super(itemView);
        recyclerView = itemView.findViewById(R.id.the_recycler_view_id_on_the_heaedr_layout_file);
    }
}

private class PostViewHolder extends RecyclerView.ViewHolder{

    ImageView imageView;

    public PostViewHolder(View itemView) {
        super(itemView);
        imageView = itemView.findViewById(R.id.post_image_view_or_whatever);
    }
}}

И така, вашият вертикален recyclerview има Post елементите (или каквото и да е вашият пост клас) начертани вертикално, това е лесното нещо за постигане. Сега, за хоризонталния изглед, трябва да внедрите заглавка на recyclerview (вижте моя пример за адаптер). Оформлението на заглавката ще има друг хоризонтален рециклиращ изглед.

person Tiago Ornelas    schedule 25.07.2018
comment
Добре. Всичко е ясно, с изключение на начина, по който трябва да дефинирам адаптер/мениджър на оформление за хоризонтален recyclerview във вертикалния адаптер. Можете ли да ми предоставите малка мостра с тази част, моля? - person Ciobanu Razvan; 25.07.2018
comment
Редактирах кода на моите отговори. Моля, имайте предвид, че ще трябва да създадете друг адаптер (в моя пример е AnotherAdaterYouNeedToCreateForTheHorizontalRecyclerView). Този адаптер ще има хоризонталните елементи, които искате да покажете. - person Tiago Ornelas; 25.07.2018
comment
Добре, разбрах, вече е ясно. Последен въпрос. Как трябва да уведомя хоризонталния адаптер за промени? Мога ли да уведомявам по различен начин промените в емисиите и промените в историите? - person Ciobanu Razvan; 25.07.2018
comment
Отново редактирах кода. Обърнете внимание на масива feedItems и метода notifyFeedChanged, който добавих - person Tiago Ornelas; 25.07.2018
comment
А за известия за актуализации на публикации трябва да уведомя адаптера за позиции от 1 до размер на публикации, нали? - person Ciobanu Razvan; 25.07.2018
comment
Да вярно. Вероятно просто извикайте notifyDataSetChanged на целия адаптер - person Tiago Ornelas; 26.07.2018
comment
Извикването му за целия адаптер също ще обнови историите, което не е необходимо - person Ciobanu Razvan; 26.07.2018
comment
Вярно е. Освен ако не внедрите DiffResult (medium.com/@iammert/) - person Tiago Ornelas; 26.07.2018

Във вашето 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF">

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tv"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingStart="16dp"
                    android:paddingTop="8dp"
                    android:text="Welcome"
                    android:textAppearance="@style/TextAppearance.AppCompat.Large"
                    android:textColor="#000000"
                    android:textSize="24sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/date"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingStart="16dp"
                    android:paddingTop="8dp"
                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
                    android:textColor="@color/black_80" />

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/rv"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="8dp"
                    android:orientation="horizontal" />
            </LinearLayout>

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rvv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" />

        </LinearLayout>
    </androidx.core.widget.NestedScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>
person Shivang Ahuja    schedule 16.04.2020