RecyclerView не распознает жесты смахивания от ItemTouchHelper - PullRequest
1 голос
/ 01 апреля 2020

Я пытаюсь прикрепить ItemTouchHelper к моему RecyclerView, чтобы я мог провести пальцами, чтобы удалить фильмы из моего RecyclerView. Я сделал именно то, что показали онлайн-уроки, но по какой-то причине это не работает. Я подозреваю, что это потому, что я работаю с фрагментами, потому что в другом приложении, которое не использует фрагменты, он работает просто отлично. Как заставить его работать во фрагменте?

Класс WatchedListActivity:

package nl.avans.cinetopia.presentation;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.Objects;

import nl.avans.cinetopia.R;
import nl.avans.cinetopia.adapters.MoviesRecyclerViewAdapter;
import nl.avans.cinetopia.data_access.UrlBuilder;
import nl.avans.cinetopia.data_access.get_requests.GenresGetRequest;
import nl.avans.cinetopia.data_access.get_requests.ListGetRequest;
import nl.avans.cinetopia.data_access.post_requests.RemoveMovieFromList;
import nl.avans.cinetopia.data_access.utilities.JsonUtils;
import nl.avans.cinetopia.domain.Movie;

public class WatchedListActivity extends Fragment implements MoviesRecyclerViewAdapter.OnItemClickListener {
    private static final String TAG = WatchedListActivity.class.getSimpleName();

    // RecyclerView attributes
    private RecyclerView mRecyclerView;
    private MoviesRecyclerViewAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    private ArrayList<Movie> mMovies = new ArrayList<>();

    private String sessionId;
    private String watchedListId;
    private String watchListId;

    WatchedListActivity(String sessionId, String watchedListId, String watchListId) {
        this.sessionId = sessionId;
        this.watchedListId = watchedListId;
        this.watchListId = watchListId;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Confirm this fragment has menu items.
        setHasOptionsMenu(true);
    }

    @Override
    public void onPrepareOptionsMenu(@NonNull Menu menu) {
        super.onPrepareOptionsMenu(menu);
        MenuItem itemSearch = menu.findItem(R.id.action_search);
        MenuItem itemFilter = menu.findItem(R.id.action_filter);
        if (itemSearch != null) {
            itemSearch.setVisible(false);
        }
        if (itemFilter != null) {
            itemFilter.setVisible(false);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_main_fragment, container, false);

        retrieveLatestGenresFromApi();
        retrieveWatchedMoviesFromApi();

        // Obtain a handle to the object.
        mRecyclerView = view.findViewById(R.id.activity_main_recyclerView);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
        itemTouchHelper.attachToRecyclerView(mRecyclerView);
        // Use a linear layout manager.
        mLayoutManager = new LinearLayoutManager(getActivity());
        // Connect the RecyclerView to the layout manager.
        mRecyclerView.setLayoutManager(mLayoutManager);

        // Specify an adapter.
        mAdapter = new MoviesRecyclerViewAdapter(getActivity(), mMovies);
        // Connect the RecyclerView to the adapter.
        mRecyclerView.setAdapter(mAdapter);
        // Set OnItemClickListener.
        mAdapter.setOnItemClickListener(this);

        /* Add a divider to the RecyclerView. */
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(Objects.requireNonNull(getActivity()), DividerItemDecoration.VERTICAL);
        dividerItemDecoration.setDrawable(getResources().getDrawable(R.drawable.rv_divider));
        mRecyclerView.addItemDecoration(dividerItemDecoration);

        return view;
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        // Inflate the fragment menu items.
        inflater.inflate(R.menu.share_menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == R.id.action_share) {
            composeImplicitIntent();
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    private void retrieveWatchedMoviesFromApi() {
        ListGetRequest task = new ListGetRequest(new MovieApiListener());
        task.execute(UrlBuilder.buildGetListUrl(watchedListId));
    }

    private void retrieveLatestGenresFromApi() {
        GenresGetRequest task = new GenresGetRequest(new JsonUtils.GenresApiListener());
        task.execute(UrlBuilder.buildGenreUrl());
    }

    private void removeMovieFromWatchedList(int id) {
        RemoveMovieFromList task = new RemoveMovieFromList(new AsyncResponseRemove());
        task.execute(UrlBuilder.buildRemoveMovieUrl(id, sessionId, watchListId));
    }

    class MovieApiListener implements ListGetRequest.WatchedListApiListener {
        @Override
        public void handleMovieResult(ArrayList<Movie> movies) {
            Log.d(TAG, "handleMovieResult called");

            // Add all movies to our ArrayList and notify the adapter that the dataset has changed.
            mMovies.addAll(movies);
            mAdapter.notifyDataSetChanged();
        }
    }

    private void composeImplicitIntent() {
        Log.d(TAG, "composeImplicitInten aangeroepen");

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < mMovies.size(); i++) {
            builder.append(mMovies.get(i).getTitle());
            if (i != mMovies.size()) {
                builder.append("\n");
            }
        }

        Intent intent = new Intent(android.content.Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TITLE, "Film");
        intent.putExtra(Intent.EXTRA_TEXT, builder.toString());
        if (intent.resolveActivity(Objects.requireNonNull(getActivity()).getPackageManager()) != null) {
            startActivity(Intent.createChooser(intent, "Send Watched List"));
        }
    }

    @Override
    public void onItemClick(int position) {
        Objects.requireNonNull(getActivity()).getSupportFragmentManager().beginTransaction()
                .replace(R.id.activity_main_frameLayout, new MovieDetailsActivity(mMovies.get(position).getId(), sessionId, watchedListId, watchListId))
                .addToBackStack(null).commit();
    }

    private ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
            final int position = viewHolder.getAdapterPosition();

            removeMovieFromWatchedList(position);
            mAdapter.notifyItemRemoved(position);
        }
    };

    class AsyncResponseRemove implements RemoveMovieFromList.AsyncResponse {

        @Override
        public void processFinish(int output) {
            if (output == 13) {
                Toast.makeText(getActivity(), getString(R.string.remove_movie_result),
                        Toast.LENGTH_LONG).show();
            }
        }
    }
}

Класс MoviesRecyclerViewAdapter:

package nl.avans.cinetopia.adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.squareup.picasso.Picasso;

import java.util.ArrayList;

import nl.avans.cinetopia.R;
import nl.avans.cinetopia.domain.Genre;
import nl.avans.cinetopia.domain.Movie;

/**
 * Adapter class for our popular movies RecyclerView.
 */
public class MoviesRecyclerViewAdapter extends RecyclerView.Adapter<MoviesRecyclerViewAdapter.PopularMoviesViewHolder> {

    // Global attributes.
    private Context mContext;
    private ArrayList<Movie> mMovies;
    private OnItemClickListener mListener;

    public interface OnItemClickListener {
        void onItemClick(int position);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mListener = listener;
    }

    public MoviesRecyclerViewAdapter(Context context, ArrayList<Movie> movies) {
        this.mContext = context;
        this.mMovies = movies;
    }

    /**
     * Inflates a MovieViewHolder we can bind data to.
     */
    @NonNull
    @Override
    public MoviesRecyclerViewAdapter.PopularMoviesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(mContext).inflate(R.layout.list_item_main_movies, parent, false);
        return new PopularMoviesViewHolder(v);
    }

    /**
     * Binds movie data to the ViewHolder.
     */
    @Override
    public void onBindViewHolder(@NonNull MoviesRecyclerViewAdapter.PopularMoviesViewHolder holder, int position) {
        // Retrieve current movie.
        Movie currentMovie = mMovies.get(position);

        // Retrieve the movie's data.
        String title = currentMovie.getTitle();
        ArrayList<Genre> genres = currentMovie.getGenres();
        double rating = currentMovie.getRating();
        String imageUrl = currentMovie.getImageUrl();

        // Build the genre string.
        StringBuilder genreString = new StringBuilder();

        for (int i = 0; i < genres.size(); i++) {
            String name = genres.get(i).getName();

            if (i < genres.size() - 1) {
                genreString.append(name).append(", ");
            } else {
                genreString.append(name);
            }
        }

        // Bind the data to the Views of our holder.
        holder.mTextViewTitle.setText(title);
        holder.mTextViewGenre.setText(genreString.toString());
        holder.mTextViewRating.setText(String.valueOf(rating));
        Picasso.get().load(imageUrl).fit().centerInside().into(holder.mImageViewPoster);
        Picasso.get().load("https://www.themoviedb.org/assets/2/v4/logos/208x226-stacked-green-9484383bd9853615c113f020def5cbe27f6d08a84ff834f41371f223ebad4a3c.png"
        ).fit().centerInside().into(holder.mImageViewTmdb);
    }

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

    public class PopularMoviesViewHolder extends RecyclerView.ViewHolder {

        // The Views in our list item.
        ImageView mImageViewPoster;
        ImageView mImageViewTmdb;
        TextView mTextViewTitle;
        TextView mTextViewGenre;
        TextView mTextViewRating;

        // Constructor.
        PopularMoviesViewHolder(View itemView) {
            super(itemView);
            mImageViewPoster = itemView.findViewById(R.id.iv_movie_list_picture);
            mImageViewTmdb = itemView.findViewById(R.id.iv_tmdb_logo);
            mTextViewTitle = itemView.findViewById(R.id.tv_movie_list_title);
            mTextViewGenre = itemView.findViewById(R.id.tv_movie_list_genre);
            mTextViewRating = itemView.findViewById(R.id.tv_movie_list_rating);


            // Set an OnClickListener on the MovieViewHolder so we can click on each list item.
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mListener != null) {
                        int position = getAdapterPosition();
                        if (position != RecyclerView.NO_POSITION) {
                            mListener.onItemClick(position);
                        }
                    }
                }
            });
        }
    }
}

1 Ответ

0 голосов
/ 01 апреля 2020

добавить, если (direction == ItemTouchHelper.LEFT) это условие в методе onSwiped.

 private ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
    if(direction == ItemTouchHelper.LEFT){
            final int position = viewHolder.getAdapterPosition();

            removeMovieFromWatchedList(position);
            mAdapter.notifyItemRemoved(position);
        }
}
    };
...