Erhalten Sie beim Scrollen ein sichtbares Element von RecycleView in der Mitte

Lesezeit: 19 Minuten

Erhalten Sie beim Scrollen ein sichtbares Element von RecycleView in
Ductran

Das ist was ich will:

Geben Sie hier die Bildbeschreibung ein

Als Bild oben möchte ich eine Mittellinie zeichnen RecycleViewdann erhalten Sie das mittlere Element beim Scrollen (sowie nach links oder rechts bewegen)
Hier ist mein Versuch, eine Horizontale zu zeichnen RecycleView:

    HorizontalAdapter adapter = new HorizontalAdapter(data);
    LinearLayoutManager layoutManager
            = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
    recycleView.setLayoutManager(layoutManager);
    recycleView.setAdapter(adapter);

Gibt es eine Möglichkeit zu wissen, welches Element in die Mitte verschoben wird? RecycleView? Und wie kann ich scrollen RecycleView nach links oder rechts nur eine Position?

Aktualisieren: Ich habe versucht, einen Scroll-Listener zu verwenden, um die mittlere Position zu erhalten, aber es funktioniert nicht als Aspekt.

  @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            int firstPos = layoutManager.findFirstVisibleItemPosition();
            int lastPos = layoutManager.findLastVisibleItemPosition();
            int middle = Math.abs(lastPos - firstPos) / 2 + firstPos;

            int selectedPos = -1;
            for (int i = 0; i < adapter.getItemCount(); i++) {
                if (i == middle) {
                    adapter.getItem(i).setSelected(true);
                    selectedPos = i;
                } else {
                    adapter.getItem(i).setSelected(false);
                }
            }

            adapter.notifyDataSetChanged();
        }

Und erhalten Sie das Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Ich möchte das ausgewählte Element nur ändern (Text in weiße Farbe umwandeln), wenn es blau ist Rect

  • und was list_item_padding Layout enthält, können Sie mir sagen? können Sie mir sagen

    – Mahesh Suthar

    21. Dezember 16 um 5:47 Uhr


  • @MaheshSuthar es ist nur ein leeres Layout mit gleicher Elementbreite

    – Ductran

    21. Dezember 16 um 8:10 Uhr


  • tut mir leid, aber es funktioniert nicht

    – Mahesh Suthar

    21. Dezember 16 um 11:31 Uhr

  • Können Sie mir sagen, wie es funktioniert, wenn der Benutzer auf das Datum klickt und das Datum in der Mitte steht?

    – Mahesh Suthar

    21. Dezember 16 um 12:11 Uhr

  • @MaheshSuthar Was hast du versucht? Wenn es nicht funktionieren kann, sollten Sie eine andere Frage erstellen. Versuchen Sie, die Antwort von TranHieu sorgfältig zu lesen, der Algorithmus ist darauf ausgelegt. Ich habe die Antwort von TranHieu verwendet und an meine Bedürfnisse angepasst.

    – Ductran

    22. Dezember 16 um 3:10 Uhr

Ich habe so etwas gemacht. Ich kann genau das tun, was Sie brauchen. Zunächst einmal, so funktioniert meine Rechenarbeit
Geben Sie hier die Bildbeschreibung ein

Das ist mein recyclerView Adapter

public class DateAdapter extends RecyclerView.Adapter<DateAdapter.DateViewHolder> {
private ArrayList<LabelerDate> dateDataList;


private static final int VIEW_TYPE_PADDING = 1;
private static final int VIEW_TYPE_ITEM = 2;
private int paddingWidthDate = 0;

private int selectedItem = -1;

public DateAdapter(ArrayList<LabelerDate> dateData, int paddingWidthDate) {
    this.dateDataList = dateData;
    this.paddingWidthDate = paddingWidthDate;

}


@Override
public DateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == VIEW_TYPE_ITEM) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_date,
                parent, false);
        return new DateViewHolder(view);
    } else {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_padding,
                parent, false);

        RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
        layoutParams.width = paddingWidthDate;
        view.setLayoutParams(layoutParams);
        return new DateViewHolder(view);
    }
}

@Override
public void onBindViewHolder(DateViewHolder holder, int position) {
    LabelerDate labelerDate = dateDataList.get(position);
    if (getItemViewType(position) == VIEW_TYPE_ITEM) {
        if(labelerDate.dateType.equals(BirthDayActivity.DateType.C31))
                holder.tvDate.setText(String.valueOf(labelerDate.valueDate));
                holder.tvDate.setVisibility(View.VISIBLE);
                holder.imgSmall.setVisibility(View.VISIBLE);

        if (position == selectedItem) {
            holder.tvDate.setTextColor(Color.parseColor("#094673"));
            holder.tvDate.setTextSize(35);
            holder.imgSmall.setBackgroundResource(R.color.textviewbold);

        } else {
            holder.tvDate.setTextColor(Color.GRAY);
            holder.tvDate.setTextSize(35);
            holder.imgSmall.setBackgroundResource(R.color.gray);
        }
    }
}

public void setSelecteditem(int selecteditem) {
    this.selectedItem = selecteditem;
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return dateDataList.size();
}

@Override
public int getItemViewType(int position) {
    LabelerDate labelerDate = dateDataList.get(position);
    if (labelerDate.dateType.equals(BirthDayActivity.DateType.NONE)) {
        return VIEW_TYPE_PADDING;
    }
    return VIEW_TYPE_ITEM;
}


public class DateViewHolder extends RecyclerView.ViewHolder {
    public TextView tvDate;
    public ImageView imgSmall;

    public DateViewHolder(View itemView) {
        super(itemView);
        tvDate = (TextView) itemView.findViewById(R.id.tvNumberDate);
        imgSmall = (ImageView) itemView.findViewById(R.id.small_marked_dob);
    }
}}

Dies ist der wichtigste Algorithmus:

public void getRecyclerviewDate() {
    recyclerViewDate = (RecyclerView) findViewById(R.id.recyclerViewDay);
    ViewTreeObserver vtoDate = recyclerViewDate.getViewTreeObserver();
    vtoDate.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            recyclerViewDate.getViewTreeObserver().removeOnPreDrawListener(this);
            finalWidthDate = recyclerViewDate.getMeasuredWidth();
            itemWidthDate = getResources().getDimension(R.dimen.item_dob_width);
            paddingDate = (finalWidthDate - itemWidthDate) / 2;
            firstItemWidthDate = paddingDate ;
            allPixelsDate = 0;

            final LinearLayoutManager dateLayoutManager = new LinearLayoutManager(getApplicationContext());
            dateLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
            recyclerViewDate.setLayoutManager(dateLayoutManager);
            recyclerViewDate.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    synchronized (this) {
                         if(newState == RecyclerView.SCROLL_STATE_IDLE){           
                            calculatePositionAndScrollDate(recyclerView);
                        }
                    }

                }

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    allPixelsDate += dx;
                }
            });
            if (labelerDates == null)
                labelerDates = new ArrayList<>();
            labelerDates.addAll(genLabelerDate(currentMonth, currentYear));
            dateAdapter = new DateAdapter(labelerDates, (int) firstItemWidthDate);
            recyclerViewDate.setAdapter(dateAdapter);
            return true;
        }
    });
}
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/

private void calculatePositionAndScrollDate(RecyclerView recyclerView) {
    int expectedPositionDate = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);

    if (expectedPositionDate == -1) {
        expectedPositionDate = 0;
    } else if (expectedPositionDate >= recyclerView.getAdapter().getItemCount() - 2) {
        expectedPositionDate--;
    }
    scrollListToPositionDate(recyclerView, expectedPositionDate);

}
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/
private void scrollListToPositionDate(RecyclerView recyclerView, int expectedPositionDate) {
    float targetScrollPosDate = expectedPositionDate * itemWidthDate + firstItemWidthDate - paddingDate;
    float missingPxDate = targetScrollPosDate - allPixelsDate;
    if (missingPxDate != 0) {
        recyclerView.smoothScrollBy((int) missingPxDate, 0);
    }
}
private void setDateValue() {
    int expectedPositionDateColor = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);
    setColorDate = expectedPositionDateColor + 1;
    //set color here
    dateAdapter.setSelecteditem(setColorDate);
}
 @Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);   
    allPixelsDate = savedInstanceState.getFloat(BUNDLE_LIST_PIXELS_DATE);
    allPixelsDateChanged = savedInstanceState.getFloat(BUNDLE_LIST_PIXELS_DATE_CHANGED);
}

@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putFloat(BUNDLE_LIST_PIXELS_DATE, allPixelsDate);
    outState.putFloat(BUNDLE_LIST_PIXELS_DATE_CHANGED, allPixelsDateChanged);
}

Und das ist mein Ergebnis:
Geben Sie hier die Bildbeschreibung ein

Schau dieses Video an Verknüpfungdas ist meine App-Demo

  • Irgendetwas stimmt mit Ihrem Code nicht. Der paddingDate wird nie geändert. Also die Formel (allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate ist gleich allPixelsDate/itemWidthDateund geben Sie die falsch ausgewählte Position zurück

    – Ductran

    7. Januar 16 um 15:00 Uhr

  • Nun, ich denke, die Position des ersten Artikels in recyclerView (keine Auffüllung) ist 0, und sein Artikel ist Nummer 1. Das heißt, wenn Sie die richtige Nummer erhalten möchten, müssen Sie +1 geben. Ich habe es bei setDateValue() gemacht. Tks für deine Antwort

    – TranHieu

    8. Januar 16 um 3:17 Uhr

  • Meine Artikelbreite ist 100dp und meine mittlere Artikelbreite ist 200dp. Wie kann ich dies mit unterschiedlichen Artikelbreiten implementieren?

    – Ibrahim Disouki

    21. Mai 16 um 17:29 Uhr

  • @hema18 in meinem onBindViewHolder Ich habe eine Variable namens selectedItem. Schau es dir einfach an. Es entscheidet, welches Element in der Mitte ist.

    – TranHieu

    22. Mai 16 um 16:57 Uhr

  • Der Screenshot stammt von einem iOS-Gerät? Das ist etwas verwirrend.

    – Asme Just

    15. November 17 um 4:57 Uhr

1643905991 561 Erhalten Sie beim Scrollen ein sichtbares Element von RecycleView in
stillsudo

Manchmal wird der gesamte Beispielcodeblock zusammen benötigt, da wir möglicherweise etwas übersehen. Hier ist, was ich habe, fühlen Sie sich frei, etwas zu korrigieren, da ich vielleicht irgendwo einen kleinen Fehler mache. Und ja, diese Antwort ist eine Erweiterung der @tranhieu-Antwort. Danke @tranhieu.

MainActivity.java

package com.test;

import android.app.Activity;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import java.util.ArrayList;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    public float firstItemWidthDate;
    public float paddingDate;
    public float itemWidthDate;
    public int allPixelsDate;
    public int finalWidthDate;
    private DateAdapter dateAdapter;
    private ArrayList<LabelerDate> labelerDates = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getRecyclerviewDate();

    }


    public void getRecyclerviewDate() {
        final RecyclerView recyclerViewDate = (RecyclerView) findViewById(R.id.rv_tasks_date);
        if (recyclerViewDate != null) {
            recyclerViewDate.postDelayed(new Runnable() {
                @Override
                public void run() {
                    setDateValue();
                }
            }, 300);
            recyclerViewDate.postDelayed(new Runnable() {
                @Override
                public void run() {
                    recyclerViewDate.smoothScrollToPosition(dateAdapter.getItemCount()-1);
                    setDateValue();
                }
            }, 5000);
        }
        ViewTreeObserver vtoDate = recyclerViewDate.getViewTreeObserver();
        vtoDate.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {


            @Override
            public boolean onPreDraw() {
                recyclerViewDate.getViewTreeObserver().removeOnPreDrawListener(this);
                finalWidthDate = recyclerViewDate.getMeasuredWidth();
                itemWidthDate = getResources().getDimension(R.dimen.item_dob_width);
                paddingDate = (finalWidthDate - itemWidthDate) / 2;
                firstItemWidthDate = paddingDate;
                allPixelsDate = 0;

                final LinearLayoutManager dateLayoutManager = new LinearLayoutManager(getApplicationContext());
                dateLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
                recyclerViewDate.setLayoutManager(dateLayoutManager);
                recyclerViewDate.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                        super.onScrollStateChanged(recyclerView, newState);
                        synchronized (this) {
                            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                                calculatePositionAndScrollDate(recyclerView);
                            }
                        }

                    }

                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                        super.onScrolled(recyclerView, dx, dy);
                        allPixelsDate += dx;
                    }
                });
                if (labelerDates == null) {
                    labelerDates = new ArrayList<>();
                }
                genLabelerDate();
                dateAdapter = new DateAdapter(labelerDates, (int) firstItemWidthDate);
                recyclerViewDate.setAdapter(dateAdapter);
                dateAdapter.setSelecteditem(dateAdapter.getItemCount() - 1);
                return true;
            }
        });
    }

    private void genLabelerDate() {
        for (int i = 0; i < 32; i++) {
            LabelerDate labelerDate = new LabelerDate();
            labelerDate.setNumber(Integer.toString(i));
            labelerDates.add(labelerDate);

            if (i == 0 || i == 31) {
                labelerDate.setType(DateAdapter.VIEW_TYPE_PADDING);
            } else {
                labelerDate.setType(DateAdapter.VIEW_TYPE_ITEM);
            }
        }
    }
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/

    private void calculatePositionAndScrollDate(RecyclerView recyclerView) {
        int expectedPositionDate = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);

        if (expectedPositionDate == -1) {
            expectedPositionDate = 0;
        } else if (expectedPositionDate >= recyclerView.getAdapter().getItemCount() - 2) {
            expectedPositionDate--;
        }
        scrollListToPositionDate(recyclerView, expectedPositionDate);

    }

    /* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/
    private void scrollListToPositionDate(RecyclerView recyclerView, int expectedPositionDate) {
        float targetScrollPosDate = expectedPositionDate * itemWidthDate + firstItemWidthDate - paddingDate;
        float missingPxDate = targetScrollPosDate - allPixelsDate;
        if (missingPxDate != 0) {
            recyclerView.smoothScrollBy((int) missingPxDate, 0);
        }
        setDateValue();
    }

    //
    private void setDateValue() {
        int expectedPositionDateColor = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);
        int setColorDate = expectedPositionDateColor + 1;
//        set color here
        dateAdapter.setSelecteditem(setColorDate);
    }


    public class DateAdapter extends RecyclerView.Adapter<DateAdapter.DateViewHolder> {
        private ArrayList<LabelerDate> dateDataList;


        private static final int VIEW_TYPE_PADDING = 1;
        private static final int VIEW_TYPE_ITEM = 2;
        private int paddingWidthDate = 0;

        private int selectedItem = -1;

        public DateAdapter(ArrayList<LabelerDate> dateData, int paddingWidthDate) {
            this.dateDataList = dateData;
            this.paddingWidthDate = paddingWidthDate;

        }


        @Override
        public DateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == VIEW_TYPE_ITEM) {
                final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,
                    parent, false);
                return new DateViewHolder(view);
            } else {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,
                    parent, false);

                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
                layoutParams.width = paddingWidthDate;
                view.setLayoutParams(layoutParams);
                return new DateViewHolder(view);
            }
        }

        @Override
        public void onBindViewHolder(DateViewHolder holder, int position) {
            LabelerDate labelerDate = dateDataList.get(position);
            if (getItemViewType(position) == VIEW_TYPE_ITEM) {
                holder.tvDate.setText(labelerDate.getNumber());
                holder.tvDate.setVisibility(View.VISIBLE);

                Log.d(TAG, "default " + position + ", selected " + selectedItem);
                if (position == selectedItem) {
                    Log.d(TAG, "center" + position);
                    holder.tvDate.setTextColor(Color.parseColor("#76FF03"));
                    holder.tvDate.setTextSize(35);

                } else {
                    holder.tvDate.setTextColor(Color.WHITE);
                    holder.tvDate.setTextSize(18);
                }
            } else {
                holder.tvDate.setVisibility(View.INVISIBLE);
            }
        }

        public void setSelecteditem(int selecteditem) {
            this.selectedItem = selecteditem;
            notifyDataSetChanged();
        }

        @Override
        public int getItemCount() {
            return dateDataList.size();
        }

        @Override
        public int getItemViewType(int position) {
            LabelerDate labelerDate = dateDataList.get(position);
            if (labelerDate.getType() == VIEW_TYPE_PADDING) {
                return VIEW_TYPE_PADDING;
            } else {
                return VIEW_TYPE_ITEM;
            }

        }


        public class DateViewHolder extends RecyclerView.ViewHolder {
            public TextView tvDate;

            public DateViewHolder(View itemView) {
                super(itemView);
                tvDate = (TextView) itemView.findViewById(R.id.txt_date);
            }
        }
    }

    private class LabelerDate {
        private int type;
        private String number;

        public String getNumber() {
            return number;
        }

        public void setNumber(String number) {
            this.number = number;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_tasks_date"
            android:layout_width="match_parent"
            android:layout_height="48dp" />

        <ImageView
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_gravity="center"
            android:layout_marginTop="48dp"
            android:src="https://stackoverflow.com/questions/34586637/@android:drawable/ic_dialog_info" />
    </FrameLayout>

</LinearLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical" android:layout_width="wrap_content"
              android:layout_height="match_parent">

    <TextView
        android:id="@+id/txt_date"
        android:layout_width="@dimen/item_dob_width"
        android:layout_height="48dp"
        android:text="32"
        android:textColor="@android:color/white"
        android:background="@android:color/darker_gray"
        android:textSize="28sp"
        android:gravity="center"/>

</LinearLayout>

Abmessungen.xml

<resources>
    <dimen name="item_dob_width">100dp</dimen>
</resources>

  • Wenn ich mehrere horizontale Bildlaufansichten verwenden muss als?

    – Krunal Doshi

    21. September 16 um 12:41 Uhr

  • stackoverflow.com/questions/39820788/… Können Sie mir dabei helfen

    – Krunal Doshi

    3. Oktober 16 um 7:26 Uhr


  • Wie kann ich es für vertikale Recyclerview tun?

    – Basant

    15. Oktober 18 um 12:05 Uhr

Oh Junge. Ich habe fast eine Woche nach dieser Antwort gesucht und dann die Lösung gefunden. Brauch LayoutManagers? Nein. ItemDecorator? NÖ.

Hier ist der einfachste Weg, es zu tun:

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:paddingStart="150dp"
    android:paddingEnd="150dp"
    android:clipToPadding="false" />

Der kritische Teil ist:

    android:paddingStart="150dp"
    android:paddingEnd="150dp"
    android:clipToPadding="false"

Und dann einfach zuweisen SnapHelper zu deinem RecylcerView:

val snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(recyclerView)

Das ist es. Die einfachste und perfekteste Lösung für das Problem

  • Diese Lösung funktioniert nur, wenn die RecyclerViewer Breite und die Breite des ersten und letzten Elements ist so, dass 150dp = RV.width * 0.5f - item.width * 0.5f Ändert sich die Artikelbreite gegenüber der RecyclerView Die ersten und letzten Elemente werden immer falsch ausgerichtet, da dies auf der Verwendung statischer Breiten für das RV und seine Elemente beruht und erwartet, dass sie immer fest bleiben. Es ist keine sehr gute Lösung wegen des völligen Mangels an Flexibilität.

    – Schatten

    16. November 20 um 15:42 Uhr


Ich verwende den SnapHelper genau hier:

    // init snaphelper        
    SnapHelper snapHelper = new LinearSnapHelper();
    snapHelper.attachToRecyclerView(recyclerView)

    // init layout manager
    LinearLayoutManager layoutManager = new LinearLayoutManager(mainActivity);
    layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
    recyclerView.setLayoutManager(layoutManager);

    // init adapter
    adatper.setSnapHelper(snapHelper);
    adatper.setLayoutManager(layoutManager);

    adatper.initAdapter(new Float((DisplayHelper.getDisplayWidth(mainActivity) / 2) - (fooViewWidth / 2)).intValue());
    recyclerView.setAdapter(adatper);

Wie von TranHieu gesagt, ist die Lösung zum Einfügen von 2 Artikeln zum Auffüllen (an der Start- und an der Endposition) gut.

Ich mag die Verwendung von ViewTreeObserver wegen der schlechten Lesbarkeit des Codes nicht. Bei dieser Technik müssen Sie auch das Neuzeichnen der Elemente verwalten, wenn sie recycelt werden.

Wenn Sie benutzerdefinierte Ansichtsklassen verwenden, können Sie die Breite direkt in diesen Klassen festlegen.

Das ist zum Beispiel meine Padding-Klasse

/**
 * Created by firegloves on 25/09/15.
 */
@EViewGroup(R.layout.view_padding)
public class PaddingView extends FooView {

    Context mCtx;

    public PaddingView(Context context) {
        super(context);
        mCtx = context;
    }


    public void setWidth(int width) {
        setLayoutParams(new LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
    }

}

In meinem Adapter speichere ich die gewünschte Padding-Item-Breite, also gleich (displayWidth / 2) – (realItemWidth / 2)

Dies ist mein Adapter, schauen Sie sich keine Methoden an, die nicht mit RecyclerView.Adapter übereinstimmen, achten Sie auf die Methode initAdapter und die Methode onCreateItemView

@EBean
public class FooAdapterRecycler extends RecyclerViewAdapterBase<Foo, FooView> {

    private final int TYPE_PADDING_VIEW = 0;
    private final int TYPE_REAL_VIEW = 1;

    @RootContext
    Context ctx;
    @Bean(Finder.class)
    IFinder finder;

    SnapHelper snapHelper;
    RecyclerView.LayoutManager layoutManager;

    private int paddingWidth = 0;

    /**
     * preleva i dati dal finder
     */
    public void initAdapter(int paddingWidth) {

        /*******************************
         * THIS CODE IS THE IMPORTANT ONE
         ******************************/

        this.paddingWidth = paddingWidth;

        // add 1 item for initial space
        mItems = new ArrayList<>();
        Foo foo = new Foo();
        mItems.add(foo);

        // get real items from finder
        mItems.addAll(finder.findAll());

        // add 1 item for final space
        mItems = new ArrayList<>();
        Foo foo2 = new Foo();
        mItems.add(foo2);

    }


    @Override
    public int getItemViewType(int position) {
        if (position == 0 || position == getItemCount()-1) {
            return TYPE_PADDING_VIEW;
        } else {
            return TYPE_REAL_VIEW;
        }
    }

    @Override
    protected FooView onCreateItemView(ViewGroup parent, int viewType) {

        /*******************************
         * THIS CODE IS THE IMPORTANT ONE
         ******************************/

        if (viewType == TYPE_PADDING_VIEW) {
            PaddingView view = PaddingView_.build(ctx);
            view.setWidth(paddingWidth);
            return view;
        } else {
            return FooView_.build(ctx);
        }
    }

    public void setSnapHelper(SnapHelper snapHelper) {
        this.snapHelper = snapHelper;
    }

    public void setLayoutManager(RecyclerView.LayoutManager layoutManager) {
        this.layoutManager = layoutManager;
    }
}

Ich verwende die AndroidAnnotations-Bibliothek, aber sie ist nicht erforderlich

hoffentlich hilft das

1643905991 463 Erhalten Sie beim Scrollen ein sichtbares Element von RecycleView in
Dionis Beqiraj

VERWENDUNG VON SNAPHELPER – EINE REIBUNGSLOSE LÖSUNG

Hier ist es eine andere Lösung mit SnapHelper. Ausgehend von der Antwort von @TranHieu hier:

https://stackoverflow.com/a/34647005/3944251

und das komprimierte von @sector11 hier:

https://stackoverflow.com/a/38411582/3944251

Ich habe den folgenden Code geschrieben, der auch auf den beiden obigen Antworten basiert, aber einfacher ist und eine reibungslosere Lösung mit SnapHelper bietet, die in vorgestellt wird Android-Unterstützungsbibliothek 24.2.0.

Hier haben Sie die Hauptaktivität Klasse. Der Rest ist der gleiche wie bei der Antwort von @ Sector11.

import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSnapHelper;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();

    public float firstItemWidthDate;
    public float itemWidthDate;
    public int allPixelsDate;
    public int finalWidthDate;
    private DateAdapter dateAdapter;
    private ArrayList<LabelerDate> labelerDates;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        labelerDates = new ArrayList<>();
        getRecyclerviewDate();

    }


    public void getRecyclerviewDate() {
        final RecyclerView recyclerViewDate = (RecyclerView) findViewById(R.id.rv_tasks_date);
        recyclerViewDate.postDelayed(new Runnable() {
            @Override
            public void run() {
                //recyclerViewDate.smoothScrollToPosition(dateAdapter.getItemCount()-1);
                setDateValue();
            }
        }, 300);
        ViewTreeObserver vtoDate = recyclerViewDate.getViewTreeObserver();
        vtoDate.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

            @Override
            public boolean onPreDraw() {
                recyclerViewDate.getViewTreeObserver().removeOnPreDrawListener(this);
                finalWidthDate = recyclerViewDate.getMeasuredWidth();
                itemWidthDate = getResources().getDimension(R.dimen.item_dob_width);
                firstItemWidthDate = (finalWidthDate - itemWidthDate) / 2;
                allPixelsDate = 0;

                final LinearLayoutManager dateLayoutManager = new LinearLayoutManager(getApplicationContext());
                dateLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
                recyclerViewDate.setLayoutManager(dateLayoutManager);

                /* Create a LinearSnapHelper and attach the recyclerView to it. */
                final LinearSnapHelper snapHelper = new LinearSnapHelper();
                snapHelper.attachToRecyclerView(recyclerViewDate);

                recyclerViewDate.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                        allPixelsDate += dx;
                        recyclerView.post(new Runnable() {
                            public void run() {
                                setDateValue();
                            }
                        });
                    }
                });

                genLabelerDate();
                dateAdapter = new DateAdapter(labelerDates, (int) firstItemWidthDate);
                recyclerViewDate.setAdapter(dateAdapter);
                dateAdapter.setSelecteditem(dateAdapter.getItemCount() - 1);
                return true;
            }
        });
    }

    private void genLabelerDate() {
        for (int i = 0; i < 32; i++) {
            LabelerDate labelerDate = new LabelerDate();
            labelerDate.setNumber(Integer.toString(i));
            labelerDates.add(labelerDate);

            if (i == 0 || i == 31) {
                labelerDate.setType(DateAdapter.VIEW_TYPE_PADDING);
            } else {
                labelerDate.setType(DateAdapter.VIEW_TYPE_ITEM);
            }
        }
    }

    //
    private void setDateValue() {
        int expectedPositionDateColor = Math.round(allPixelsDate / itemWidthDate);
        int setColorDate = expectedPositionDateColor + 1;
//        set color here
        dateAdapter.setSelecteditem(setColorDate);
    }


    public class DateAdapter extends RecyclerView.Adapter<DateAdapter.DateViewHolder> {
        private ArrayList<LabelerDate> dateDataList;


        private static final int VIEW_TYPE_PADDING = 1;
        private static final int VIEW_TYPE_ITEM = 2;
        private int paddingWidthDate = 0;

        private int selectedItem = -1;

        public DateAdapter(ArrayList<LabelerDate> dateData, int paddingWidthDate) {
            this.dateDataList = dateData;
            this.paddingWidthDate = paddingWidthDate;

        }


        @Override
        public DateAdapter.DateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
            if (viewType == VIEW_TYPE_PADDING) {
                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
                layoutParams.width = paddingWidthDate;
                view.setLayoutParams(layoutParams);
            }
            return new DateViewHolder(view);
        }

        @Override
        public void onBindViewHolder(DateAdapter.DateViewHolder holder, int position) {
            LabelerDate labelerDate = dateDataList.get(position);
            if (getItemViewType(position) == VIEW_TYPE_ITEM) {
                holder.tvDate.setText(labelerDate.getNumber());
                holder.tvDate.setVisibility(View.VISIBLE);

                Log.d(TAG, "default " + position + ", selected " + selectedItem);
                if (position == selectedItem) {
                    Log.d(TAG, "center" + position);
                    holder.tvDate.setTextColor(Color.parseColor("#76FF03"));
                    holder.tvDate.setTextSize(35);

                } else {
                    holder.tvDate.setTextColor(Color.WHITE);
                    holder.tvDate.setTextSize(18);
                }
            } else {
                holder.tvDate.setVisibility(View.INVISIBLE);
            }
        }

        public void setSelecteditem(int selecteditem) {
            this.selectedItem = selecteditem;
            notifyDataSetChanged();
        }

        @Override
        public int getItemCount() {
            return dateDataList.size();
        }

        @Override
        public int getItemViewType(int position) {
            LabelerDate labelerDate = dateDataList.get(position);
            if (labelerDate.getType() == VIEW_TYPE_PADDING) {
                return VIEW_TYPE_PADDING;
            } else {
                return VIEW_TYPE_ITEM;
            }

        }


        public class DateViewHolder extends RecyclerView.ViewHolder {
            public TextView tvDate;

            public DateViewHolder(View itemView) {
                super(itemView);
                tvDate = (TextView) itemView.findViewById(R.id.txt_date);
            }
        }
    }

    private class LabelerDate {
        private int type;
        private String number;

        public String getNumber() {
            return number;
        }

        public void setNumber(String number) {
            this.number = number;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }
    }
}

  • Aber das erste Element beginnt in der Mitte. Also der letzte Artikel. Wie lässt sich das erste Element von links und das letzte Element von rechts starten?

    – Ankit Kamboj

    8. Februar 18 um 13:28 Uhr


  • @Dionis, was ist “item_db_width”?

    – Manikandan

    20. August 18 um 7:49 Uhr

  • Ich weiß nicht, was ich für “item_db_width” geben soll. Ich gebe nur 20 dafür. Und das mittlere Element wird beim ersten Laden ausgewählt. Beim manuellen Scrollen wird das mittlere Element nicht ausgewählt.

    – Manikandan

    20. August 18 um 08:57 Uhr

  • @Manikandan item_dob_width ist der in definierte Wert item.xml in der Antwort von @ Sector11 hier: stackoverflow.com/a/38411582/3944251. Kopiere alles .xml Dateien aus seiner Antwort und Kopie MyActivity Code aus meiner Antwort, um eine Vorstellung davon zu bekommen, wie es funktioniert.

    – Dionis Beqiraj

    21. August 18 um 08:21 Uhr

1643905992 784 Erhalten Sie beim Scrollen ein sichtbares Element von RecycleView in
Paresh Mangukiya

Wie in der anderen Antwort erwähnt, gibt es keine direkte Möglichkeit, dies zu tun.

Auf diese Weise können Sie wahrscheinlich das erreichen, was Sie in der Frage beschrieben haben.

  1. Kennen Sie die Anzahl der auf dem Bildschirm sichtbaren Elemente.
  2. Wählen Sie das mittlere Element programmgesteuert jedes Mal aus, wenn die Ansicht gescrollt wird.
  3. Behalten Sie ein teilweise transparentes Bild als Overlay auf dem mittleren Element in der Recycleransicht bei. (Sie müssen die Koordinaten basierend auf der Breite der Recycler-Ansicht oder der Breite des Bildschirms und der Breite des Überlagerungsbilds berechnen, das Sie einfügen möchten.
  4. Aktualisiert den ausgewählten Wert in einer Textansicht unterhalb der Recycler-Ansicht bei jedem Bildlauf.

Die Bildüberlagerungen müssen so platziert werden, dass sie zusammenhängend und als ein einziges Steuerelement erscheinen.

  • Aber das erste Element beginnt in der Mitte. Also der letzte Artikel. Wie lässt sich das erste Element von links und das letzte Element von rechts starten?

    – Ankit Kamboj

    8. Februar 18 um 13:28 Uhr


  • @Dionis, was ist “item_db_width”?

    – Manikandan

    20. August 18 um 7:49 Uhr

  • Ich weiß nicht, was ich für “item_db_width” geben soll. Ich gebe nur 20 dafür. Und das mittlere Element wird beim ersten Laden ausgewählt. Beim manuellen Scrollen wird das mittlere Element nicht ausgewählt.

    – Manikandan

    20. August 18 um 08:57 Uhr

  • @Manikandan item_dob_width ist der in definierte Wert item.xml in der Antwort von @ Sector11 hier: stackoverflow.com/a/38411582/3944251. Kopiere alles .xml Dateien aus seiner Antwort und Kopie MyActivity Code aus meiner Antwort, um eine Vorstellung davon zu bekommen, wie es funktioniert.

    – Dionis Beqiraj

    21. August 18 um 08:21 Uhr

1643905992 749 Erhalten Sie beim Scrollen ein sichtbares Element von RecycleView in
veeyikpong

Sie können eine verwenden LinearSnapHelper

An Ihren Recycler anhängenGefällt mir anzeigen

val snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(this)

Verwenden Sie dann, um die Mittelansicht zu erhalten
snapHelper.findSnapView(horizontalScrollView.layoutManager)?

.

757540cookie-checkErhalten Sie beim Scrollen ein sichtbares Element von RecycleView in der Mitte

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy