Wątek przeniesiony 2018-04-30 16:35 z Java przez somekind.

fragment jako item w recyclerView w android studio

0

Czesc,
ma ktos moze pomysl jak wykonac powyzsze czarymary? Najpierw podam przyklad o ktorym mowie zeby bylo latwiej sobie wyobrazic problem.

Otoz mamy czesc aplikacji ktora jest odpowiedzialna za pokazanie listy uczestnikow, ktora wziela udzial w konkretnej aktywnosci np. pilka nozna.
Do tego etapu nie bylo problemu, ale chcialbym, aby uzytkownicy mieli opcje ocenienia siebie nawzajem po zakonczonej aktywnosci tzn like/dislike co zamiescilem we fragmencie. Teraz chcialbym jakos polaczyc funkcje ocen z funckja wyswietlania uzytkownik przy pomocy recyclerView. Ponizej podaje kod i obrazek.

Obrazek:
[url=http://ifotos.pl/z/qnasphn/][img]http://s6.ifotos.pl/mini/obrazekpn_qnasphn.png[/img][/url]

kod recyclerView:

public class RecyclerAdapterParticipantsOfActivity extends RecyclerView.Adapter<RecyclerAdapterParticipantsOfActivity.MyViewHolder> {
    private List<Post> participantsList;
    private Context context;

    public RecyclerAdapterParticipantsOfActivity(List<Post> contacts,Context context){
        this.participantsList =contacts;
        this.context = context;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)  //parent - kontener z informacjami. Layoutinflater laczy kontener(parent)
    // z userslist
    { // view podstawowa klasa po ktorej dziedzicza kontrolki
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.participans_of_activity,parent,false);
        return new MyViewHolder(view);  //tworzy
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        final int userId;
         userId= participantsList.get(position).getUser_id();
        holder.whoTv.setText(participantsList.get(position).getLogin());   //laczy

        String img =participantsList.get(position).getImage_url();

        Picasso.with(context)
                .load(img)
                .into(holder.imageViewRecycler);

        holder.ProfileBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final Context context;
                final Intent intent;
                context = v.getContext();
                intent =  new Intent(context, Profile.class);
                intent.putExtra("idProfil",userId);
                context.startActivity(intent);
            }
        });

        holder.FriendsBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final Context context;
                context = v.getContext();
                Friends friends = new Friends();
                friends.AddFriend(Login.currentUserId, userId,context);

            }
        });

        holder.MessageBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                final Context context;
                final Intent intent;
                context = v.getContext();
                intent =  new Intent(context, Chat.class);
                intent.putExtra("IdReciver",userId);
                context.startActivity(intent);

            }
        });





    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder{
        private  TextView whoTv;
        private  Button ProfileBt,FriendsBt,MessageBt;
        private ImageView imageViewRecycler;

        public MyViewHolder(View itemView) {
            super(itemView);

            imageViewRecycler =(ImageView) itemView.findViewById(R.id.participantsImage);

            whoTv = (TextView) itemView.findViewById(R.id.LoginParticipantsTvId);
            ProfileBt =(Button) itemView.findViewById(R.id.ProfilParticipantsBtId);
            FriendsBt =(Button) itemView.findViewById(R.id.FriendsProfilParticipantsBtId);
            MessageBt =(Button) itemView.findViewById(R.id.MessageParticipantsBtId);
        }
    }
}

kod fragmentu:

public class Fragment_participants extends Fragment {
    private static final String TAG = "Fragment_participants";
    private TextView likeTv, disLikeTv;
    private ToggleButton likeToggle, dislikeToggle;
    private APIService apiServiceRate;
    private List<Post> rateList;
    private int rateDb, rating_main;
    private boolean checkLike, checkDisLike;
    private String zero = Integer.toString(0);

    public Fragment_participants() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {



        View view = inflater.inflate(R.layout.fragment_fragment_participants, container, false);

        apiServiceRate= ApiUtils.getAPIService();
        likeTv = (TextView) view.findViewById(R.id.likeTvFragment);
        disLikeTv = (TextView) view.findViewById(R.id.disLikeTvFragment);
        likeToggle = (ToggleButton) view.findViewById(R.id.togglebt);
        dislikeToggle = (ToggleButton) view.findViewById(R.id.togglebt2);

        likeToggle.setText(null);
        likeToggle.setTextOn(null);
        likeToggle.setTextOff(null);

        dislikeToggle.setText(null);
        dislikeToggle.setTextOn(null);
        dislikeToggle.setTextOff(null);



        likeToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Log.i("KM", "like change + " + isChecked);
                if(isChecked) {
                    likeToggle.setBackgroundResource(R.drawable.likeclicked);
                } else {
                    likeToggle.setBackgroundResource(R.drawable.like);
                }
            }
        });

        dislikeToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Log.i("KM", "dislike change + " + isChecked);
                if(isChecked)
                    dislikeToggle.setBackgroundResource(R.drawable.dislikeclicked);
                else {
                    dislikeToggle.setBackgroundResource(R.drawable.dislike);
                }

            }
        });

        likeToggle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("KM", "like nClickListener");
                checkLike = ((ToggleButton) v).isChecked();
                like(checkLike);
            }
        });

        dislikeToggle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("KM", "dislike nClickListener");
                checkDisLike = ((ToggleButton) v).isChecked();
                dislike(checkDisLike);
            }
        });

        //draw background on like/dislike

        getRate(Login.currentUserId, 249);

        return view;

    }
    public void like(boolean likeStatus){

        if (likeStatus) {


            addRate(Login.currentUserId, 1, 1, 249);

        } else {

            addRate(Login.currentUserId, 1, -1, 249);
        }

    }

    public void dislike(boolean likeStatus){

        if (likeStatus) {

            addRate(Login.currentUserId, 1, -1, 249);

        } else {

            addRate(Login.currentUserId, 1, 1, 249);
        }

    }


    public void addRate(int user_id, int rater_id, int rate, int activity_id) {

        Call<List<Post>> call = apiServiceRate.addRateInterface(user_id, rater_id, rate, activity_id);
        call.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(@NonNull Call<List<Post>> call, @NonNull Response<List<Post>> response) {
                rateList=response.body();
                rateDb=rateList.get(0).getRate();
                rating_main=rateList.get(0).getRating_main();
                String rateDbInt = Integer.toString(rateDb);
                String rating_mainInt =Integer.toString(rating_main);
                if(rateDb==1) {
                    showResponse(likeTv, rateDbInt);
                    showResponse(disLikeTv, zero);
                }
                else if(rateDb==-1) {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv,zero );
                }
                else {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv, rateDbInt);
                }
                Log.i("ratesuccess", "getting data success." +  rateList);

            }

            @Override
            public void onFailure(@NonNull Call<List<Post>> call, @NonNull Throwable t) {

                Log.e("ratenotsuccess", "getting data failed." + t);

            }
        });



    }



    public void getRate(int user_id, int activity_id) {

        Call<List<Post>> call = apiServiceRate.getRateInterface(user_id, activity_id);
        call.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(@NonNull Call<List<Post>> call, @NonNull Response<List<Post>> response) {
                rateList=response.body();
                rateDb=rateList.get(0).getRate();
                rating_main=rateList.get(0).getRating_main();
                String rateDbInt = Integer.toString(rateDb);
                String rating_mainInt =Integer.toString(rating_main);

                if(rateDb==1) {
                    showResponse(likeTv, rateDbInt);
                    showResponse(disLikeTv, zero);
                }
                else if(rateDb==-1) {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv,zero );
                }
                else {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv, rateDbInt);
                }



                if(rateDb==1){
                    likeToggle.toggle();
                }
                else if(rateDb==-1){
                    dislikeToggle.toggle();
                }


                Log.i("ratesghfssdghuccess", "getting data success." + rateDb);

            }

            @Override
            public void onFailure(@NonNull Call<List<Post>> call, @NonNull Throwable t) {

                Log.e("ratenotsertjqaguccess", "getting data failed." + t);

            }
        });



    }

    private void showResponse(TextView textView, String response) {
        if ((textView.getVisibility() == View.GONE) && response!=null && response!="") {
            textView.setVisibility(View.VISIBLE);
        }
        textView.setText(response);
    }

}

chcialbym aby system like'ow byl w formie fragmentu bo potem bede mial jeszcze sekcje posty w recyclerview i pod to tez chcialbym podpiac ten system ocen.

1

IMO lepiej jest zrobić custom view dla każdego z elementów. Logika pozostaje po stronie kontrolki (dokładnie mówiąc jej presentera). Potem tylko taką kontrolkę wpychasz do widoku i reszta dzieje się już bez Twojej ingerencji. Fragment według mnie jest za duży i za ciężki na takie proste operacje.

0

Nie wiem czy nie szybciej dla mnie bedzie ogarnac ten fragment jako item. Nigdy nie dzialalem przy custom view i tutaj juz zupelnie nie wiem jak sie do tego zabrac i polaczyc calosc. Cos o tym poczytalem, ale zeby to ogarnac + zaimplementowac to wydaje sie ze wiecej roboty.

Edit: znalazlem jakies info o podawaniu fragmentu jako item w listview i faktycznie nie polecaja. Masz moze jakis fragment kodu, ktory bylby zblizony do tego co opisales?

1

Jakoś nie do końca rozumiem twój problem. Jeśli chcesz współdzielić gdzieś kawałki layoutu, to poczytaj o include i merge. Jeśli to ma być tylko jako item listy, to dalej nie pojmuję po co chcesz tam wpychać fragment i co by ci to miało dać za korzyść, skoro i tak layout definiujesz tylko raz.

No chyba, że chcesz, żeby każdy item realizował sam w sobie jakąś logikę, wtedy rzeczywiście, powinieneś zrobić własny View i w nim zamknąć całą logikę.

0

Ok wiec chcialbym zrobic custom view, najlepiej w jednej klasie zamykajac te 2 togglebutton (like, dislike) oraz licznik like/dislike. Pytanie czy da sie ta logike zamknac w jednej klasie, a nastepnie uzyc tego custom view jako jednego widgetu? Zeby uzyc tego jako widgetu z tego co poczytalem nalezy rozszerzyc klase View, ale w tym momencie nie moge skorzystac z onCreate i sciagnac danych z bazy danych itp. + kilka innych funkcji. Wiem ze moge to wszystko porozbijac i oprzec o sama kontrolke o zachowaniu w konkretny sposob w zaleznosci jaka wartosc parametru zostanie przeslana, ale czy nie da sie tego zalatwic szybciej? tzn wkleic kod i zrobic z tego View zawierajacy te 4 widgety? Generalnie slabo ogarniam androida, nigdy nie studiowalem it, nie pracowalem w it, nie zglebialem go od podstaw. Ucze sie tego co mi na bieŻąco potrzebne. Jesli ktos ma pomysl jak szybciej to zrobic niz podalem wyzej to prosilbym o jakis algorytm(fajnie by bylo gdyby byl z interfejsami) to sobie to ogarne, Chyba ze nie ma szybszego sposobu to na piechote to naklepie... Ale dlatego chcialem fragmentu uzyc zeby nie rozbijac tego na kilka klas , parametryzowac itd bo to duuuzo zabawy.

podaje 2 kody

public class Like_Dislike_System extends AppCompatActivity {
    private TextView likeTv, disLikeTv;
    private ToggleButton likeToggle, dislikeToggle;
    private APIService apiServiceRate;
    private List<Post> rateList;
    private int rateDb, rating_main;
    boolean checkLike, checkDisLike;
    private   String zero = Integer.toString(0);

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


        apiServiceRate= ApiUtils.getAPIService();
        likeTv = (TextView) findViewById(R.id.likeTvFragment);
        disLikeTv = (TextView) findViewById(R.id.disLikeTvFragment);
        likeToggle = (ToggleButton) findViewById(R.id.togglebt);
        dislikeToggle = (ToggleButton) findViewById(R.id.togglebt2);

        likeToggle.setText(null);
        likeToggle.setTextOn(null);
        likeToggle.setTextOff(null);

        dislikeToggle.setText(null);
        dislikeToggle.setTextOn(null);
        dislikeToggle.setTextOff(null);



        likeToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Log.i("KM", "like change + " + isChecked);
                if(isChecked) {
                    likeToggle.setBackgroundResource(R.drawable.likeclicked);
                } else {
                    likeToggle.setBackgroundResource(R.drawable.like);
                }
            }
        });

        dislikeToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Log.i("KM", "dislike change + " + isChecked);
                if(isChecked)
                    dislikeToggle.setBackgroundResource(R.drawable.dislikeclicked);
                else {
                    dislikeToggle.setBackgroundResource(R.drawable.dislike);
                }

            }
        });

        likeToggle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("KM", "like nClickListener");
                checkLike = ((ToggleButton) v).isChecked();
                like(checkLike);
            }
        });

        dislikeToggle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("KM", "dislike nClickListener");
                checkDisLike = ((ToggleButton) v).isChecked();
                dislike(checkDisLike);
            }
        });

        //draw background on like/dislike

        getRate(Login.currentUserId, 40);


    }

    public void like(boolean likeStatus){

        if (likeStatus) {


            addRate(Login.currentUserId, 1, 1, 40);

        } else {

            addRate(Login.currentUserId, 1, -1, 40);
        }

    }

    public void dislike(boolean likeStatus){

        if (likeStatus) {

            addRate(Login.currentUserId, 1, -1, 40);

        } else {

            addRate(Login.currentUserId, 1, 1, 40);
        }

    }


    public void addRate(int user_id, int rater_id, int rate, int activity_id) {

        Call<List<Post>> call = apiServiceRate.addRateInterface(user_id, rater_id, rate, activity_id);
        call.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(@NonNull Call<List<Post>> call, @NonNull Response<List<Post>> response) {
                rateList=response.body();
                rateDb=rateList.get(0).getRate();
                rating_main=rateList.get(0).getRating_main();
                String rateDbInt = Integer.toString(rateDb);
                String rating_mainInt =Integer.toString(rating_main);
                if(rateDb==1) {
                    showResponse(likeTv, rateDbInt);
                    showResponse(disLikeTv, zero);
                }
                else if(rateDb==-1) {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv,zero );
                }
                else {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv, rateDbInt);
                }
                Log.i("ratesuccess", "getting data success." +  rateList);

            }

            @Override
            public void onFailure(@NonNull Call<List<Post>> call, @NonNull Throwable t) {

                Log.e("ratenotsuccess", "getting data failed." + t);

            }
        });



    }



    public void getRate(int user_id, int activity_id) {

        Call<List<Post>> call = apiServiceRate.getRateInterface(user_id, activity_id);
        call.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(@NonNull Call<List<Post>> call, @NonNull Response<List<Post>> response) {
                rateList=response.body();
                rateDb=rateList.get(0).getRate();
                rating_main=rateList.get(0).getRating_main();
                String rateDbInt = Integer.toString(rateDb);
                String rating_mainInt =Integer.toString(rating_main);

                if(rateDb==1) {
                    showResponse(likeTv, rateDbInt);
                    showResponse(disLikeTv, zero);
                }
                else if(rateDb==-1) {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv,zero );
                }
                else {
                    showResponse(disLikeTv, rateDbInt);
                    showResponse(likeTv, rateDbInt);
                }



                if(rateDb==1){
                    likeToggle.toggle();
                }
                else if(rateDb==-1){
                    dislikeToggle.toggle();
                }


                Log.i("ratesghfssdghuccess", "getting data success." + rateDb);

            }

            @Override
            public void onFailure(@NonNull Call<List<Post>> call, @NonNull Throwable t) {

                Log.e("ratenotsertjqaguccess", "getting data failed." + t);

            }
        });



    }

    private void showResponse(TextView textView, String response) {
        if ((textView.getVisibility() == View.GONE) && response!=null && response!="") {
            textView.setVisibility(View.VISIBLE);
        }
        textView.setText(response);
    }
}

XML

  <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:custom="http://schemas.android.com/apk/res-auto"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentStart="true"
            android:layout_marginStart="23dp">

            <ToggleButton
                android:id="@+id/togglebt"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:background="@drawable/like" />


            <TextView
                android:id="@+id/likeTvFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBaseline="@+id/disLikeTv"
                android:layout_alignBottom="@+id/disLikeTv"
                android:layout_marginBottom="5dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_marginTop="5dp"
                android:layout_toEndOf="@+id/likeImageRec"
                android:text="0"
                android:textColor="@color/green"
                android:textSize="25dp" />

            <TextView
                android:id="@+id/disLikeTvFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="5dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_marginTop="5dp"
                android:layout_toStartOf="@+id/disLikeImageRec"
                android:text="0"
                android:textColor="@color/red"
                android:textSize="25dp" />

            <ToggleButton
                android:id="@+id/togglebt2"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:background="@drawable/dislike"
                android:text="ToggleButton" />


        </LinearLayout>
1

Zabierasz się do tego od złej strony. Kod związany z RecyclerView nie powinien dbać o wykonywanie zapytań internetowych czy zapisów do bazy danych. RecyclerView ma dziesiątki optymalizacji związanych z szybkim wyświetlaniem widoków, które nie sprawdzają się do takiej pracy. Teoretycznie mógłbyś, ale musiałbyś bardzo ekstensywnie używać serwisów i dbać synchronizację danych pomiędzymi nimi a RecyclerView, co byłoby trochę skomplikowane.

Adapter powinien dawać możliwość komponentom wyżej na reagowanie, kiedy ktoś przyciśnie coś itd. W tym celu Adapter powinien np. przyjmować jakiś interfejs do obsługi zdarzeń. Wtedy ten komponent wyżej wykonuje zapytanie internetowe, czy cokolwiek jest tam potrzebne, i po tym jak się zakończy, możesz zaktualizować widok w RecyclerView zależnie od sukcesu/porażki zapytania. Przykład dla trochę innego problemu, ale w oparciu o te same zasady, pokazałem tutaj - https://4programmers.net/Forum/1464357.

Jeżeli jednak chcesz twardo brnąć w swój sposób, to możesz utworzyć swój widok w onCreateViewHolder i przekazać go do ViewHoldera. View ma na sobie kilka metod dla cyklu życia. Dwie podstawowe to onAttachedToWindow i onDetachedFromWindow. Jeżeli nie wiesz jak tworzyć własne widoki tego typu, to hasło dla Google to "Compound View". Ale będzie to bardzo nieoptymalne i błędogenne. To dopiero będzie duuuużo zabawy.

0

ok w takim razie zrobie zrobie kontrolke ktora bedzie zajmowala sie wymiana informacji z baza, zmieniala na like clicked, dodawala liczbe do licznika. Teraz moje pytanie to czy lepiej to zrobic w custom view czy stworzyc swoj widget? Tworzac custom view oraz new widget utworzyly mi sie interfejsy i patrzac po nich duzo latwiej bedzie sie do tego zabrac tworzac nowy widget. Czy dobrze mi sie wydaje?

1

Widgety służą do osadzania jakichś funkcjanolości z Twojej aplikacji w innych aplikacjach, zazwyczaj w ekranie głównym, więc widget to nie jest coś, czego tutaj potrzebujesz. Jeżeli już coś, to możesz rozszerzyć View (czy jego pochodną), ale nie widzę sensu w tym przypadku. Twój widok jest wystarczająco prosty - dwa przyciski, licznik i pewnie jakiś opis. RecyclerView ma już pojemnik na widok w postaci ViewHoldera i tam możesz dodać podstawową kontrolę taką jak rozpoznanie kliknięcia. Wystarczy utworzyć widoku z samego XMLa i wrzucić go do ViewHoldera.

W linku z mojego poprzedniego postu możesz zobaczyć, jak powiązać ze sobą klasy. W swoim Activity, czy co tam u Ciebie zarządza adapterem, musiałbyś przekazać callback. Twój callback powinien mieć dwie metody - onPostLiked(Post post) i onPostDisliked(Post post). W jego implentacji wykonywałbyś zapytanie internetowe i odpowiednio reagował na jego sukces bądź porażkę.

0

Dzieki, udalo sie rozwiazac problem w calosci :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1