Recyclerview index vom angezeigten Item und event beim wechsel

  • 5 Antworten
  • Neuster Beitrag
W

washpuda

Neues Mitglied
Threadstarter
Hallo,

ich zeige ein Bild aus einer Liste mehrerer Bilder in einem Bildausschnitt an. Auf jedem Bild habe ich ein kleines TextView zur Anzeige Bild (1/3) usw. gesetzt. Es wird immer nur ein Bild angezeigt. Durch wischen nach links oder rechts wird jeweils das nächste oder vorherige Bild angezeigt. Das funktioniert einwandfrei.

Da ich neben dem Bild weitere Informationen einer separaten ListView anzeigen möchte, benötige ich ein Event was beim Bildwechsel aufgerufen wird und eine Möglichkeit den Index des aktuellen Bildes heraus zu bekommen. Jedem Bild sind Informationen hinterlegt, die beim Bildwechsel in einem separatem Bereich angezeigt werden sollen.


Ich habe mir ein eigenes View erstellt, dass von RecyclerView abgeleitet ist. Das Bild und die zugehörigen Daten sind MPicData Objekt enthalten.

Ich habe schon eine Weile im Internet gesucht, jedoch nichts gefunden.

Code:
public class PicThumbViewer extends RecyclerView  {

    private transient List<ChangeListener> changeListener;  // eigener Listener

    private MPicData picData;  // mehrere Bilder mit Textdaten
    private RecyclerViewAdapter adapter;
    private int index = 0;  // soll den Index vom Bild erhalten??

    public PicThumbViewer(Context context) {
        super(context);
        initialize();
    }

    public PicThumbViewer(Context context,AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    public PicThumbViewer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initialize();
    }

    public void initialize(){
        adapter = new RecyclerViewAdapter();
        this.setAdapter(adapter);
        setHasFixedSize(true);
        setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
        new PagerSnapHelper().attachToRecyclerView(this);
    }


    public MPicData getPicData() {
        return picData;
    }

    public void setPicData(MPicData picData) {
        this.picData = picData;
        adapter.notifyDataSetChanged();
    }

    public MPicData getActPic() {
          return picData == null ? null : index ==  0 ?  picData :  picData.additionalPics.get(index-1);
    }

    @Override
    public void onChildAttachedToWindow(View child) {
        super.onChildAttachedToWindow(child);
        TextView textView = (TextView) ((FrameLayout)child).getChildAt(1);  // TextView zeigt Bild (1/3)
        Utils.log(textView.getText().toString());
        //        child beinhaltet entweder das erste oder das letzte item, nicht jedoch die dazwischen
        // diese Methode wird leider auch nicht bei jedem Bildwechsel aufgerufen
    }

    public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_simple_image, parent, false);
            return new RecyclerViewAdapter.MyViewHolder(view);
        }

        @Override
        public void onBindViewHolder(final MyViewHolder holder, int position) {
            if(picData.hasAdditionalPics()){
                holder.imgCntTextView.setText("(" + (position+1) + "/"+ getItemCount() + ")");
                holder.imgCntTextView.setVisibility(VISIBLE);
            }else{
                holder.imgCntTextView.setVisibility(INVISIBLE);
            }
            
                holder.imageView.setImageBitmap(position == 0 ? PicUtils.getThumbNail(picData) :
                        PicUtils.getThumbNail(picData.additionalPics.get(position-1)));
        }

        @Override
        public int getItemCount() {
            return picData == null ? 0 : 1 + (picData.hasAdditionalPics() ? picData.additionalPics.size() :0);
        }

        @Override
        public int getItemViewType(int position) {
            return super.getItemViewType(position);
        }

        public class MyViewHolder extends RecyclerView.ViewHolder {
            ImageView imageView;
            TextView imgCntTextView;

            public MyViewHolder(View view) {
                super(view);
                imageView = view.findViewById(R.id.item_simple_Image);
                imgCntTextView = view.findViewById(R.id.item_LblSimpleImgCnt);
            }
        }
    }

        // die nächsten 3 Methoden sind für mein Changelistener, wobei fireChange() das event auslöst.
        // Die frage ist wo rufe ich diese Methode auf, dass diese einmalig bei jedem Bildwechsel aufgerufen wird.
    public void addChangeListener(ChangeListener l) {
        if(changeListener == null) {
            changeListener = new ArrayList<>();
        }
        changeListener.add(l);
    }

    public void removeChangeListener(ChangeListener l) {
        changeListener.remove(l);
    }

    public void fireChange() {
        if(changeListener != null) {
            for(ChangeListener cL: changeListener) {
                cL.stateChanged(new ChangeEvent(this));
            }
        }
    }
}
Code:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/item_FrameLayoutSI"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/item_simple_Image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="4dp"
        app:srcCompat="@drawable/info_16x16" />

    <TextView
        android:id="@+id/item_LblSimpleImgCnt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:background="#74FFFFFF"
        android:gravity="clip_horizontal|end"
        android:text="TextView"
        android:textSize="12dp"/>

</FrameLayout>
 
W

washpuda

Neues Mitglied
Threadstarter
Hallo,

hat den keiner eine Idee, wie sich so etwas umsetzen lässt? Die Umsetzung von der Anzeige der Bilder war ja sehr einfach. Ich kann ich mir nicht vorstellen, dass das erkennen des gesetzten Bildes sowie ein auslösendes Event sehr kompliziert ist. Ich hoffe es hat hier jemand eine Idee? Vielen Dank schon mal vorab.
 
swa00

swa00

Moderator
Teammitglied
Was spricht denn gegen Broadcasts ?
 
W

washpuda

Neues Mitglied
Threadstarter
Hallo,

so weit ich weiß dienen Broadcast dem weitergeben bzw. verteilen von Daten auch App übergreifend. Aber ich muss ja erst einmal ein Ereignis haben, damit ich diese Verteilung auslösen kann. Es geht mir ja um das Ereignis wenn ein Wechsel erfolgt ist, und dann der der Ermittlung welches Bild gerade angezeigt wird.

mfg
 
swa00

swa00

Moderator
Teammitglied
a) Richtig , systemübergreifend , aber du musst sie auch ordentlich Handeln indem du sie registrierst und auch wieder de-registrierst.
Deinen Unique Tag kannst du selbst bestimmen.
Nein , einen Broadcast kann man auch schlichtweg nur als Klassenüberübergreifendes Triggering anwenden.
b) Dann beschreibe doch mal ein wenig genauer , wie du den Wechsel erzeugst. Den macht das system ja nicht selbst - und an dem Punkt setzt du mit den Broadcasts an.
 
W

washpuda

Neues Mitglied
Threadstarter
Hallo swa00

den Wechsel mache ich ja mit den Fingern indem ich über das aktuell angezeigte Bild wische. Durch den PagerSnapHelper wird das bild jeweils eingerastet, es wird immer nur ein Bild angezeigt.

Ich habe jetzt auch eine Lösung gefunden, obwohl ich diese nicht sehr elegant finde. Ich habe dem Recyclerview einen OnScrolllistener hinzugefügt. Über snapHelper.findSnapView(getLayoutManager()) kann ich auf die eingerastete Komponente zugreifen und die Nummer über den Text der TextView ermitteln. Da das OnScrollEvent mehrfach aufgerufen wird, feuere ich mein Event nur, wenn sich der Index tatsächlich geändert hat.

Code:
   this.addOnScrollListener(new RecyclerView.OnScrollListener(){
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                FrameLayout frameLayout = (FrameLayout) snapHelper.findSnapView(getLayoutManager());
                String cntTxt = ((TextView) frameLayout.getChildAt(1)).getText().toString(); // z.B. (3/6)
                int newIndex = Integer.parseInt(cntTxt.substring(1, cntTxt.indexOf("/"))) - 1;
                if(index != newIndex){
                    index = newIndex;
                    Utils.log( "index =  " + PicThumbViewer.this.index);
                    fireChange(index == 0 ? picData : picData.additionalPics.get(index-1)); // eigenes Event
                }

            }
        });
 
Oben Unten