Giter VIP home page Giter VIP logo

Comments (10)

rubensousa avatar rubensousa commented on August 18, 2024

Hello @mohamedriadhzrig. You need to share more information, otherwise I can't help. What issue do you have exactly?

from dpadrecyclerview.

mohamedriadhzrig avatar mohamedriadhzrig commented on August 18, 2024

Heyy,let make it easy to understand,
I'm using 2 RV in an activity,Both of them have a vertical oriontation
first one is linear and the second one is a grid with 5 span
the click on an item of the first RV update the items of the second Rv(grid one)
when I navigate in the Grid one and go back to the first RV and click to update the Grid
The grid go messy,it's like all of them are going to the first position and paging source don't stop of requestiong the server
But when I click on items of the first rv without going to the secong RV and navigate
it work fine(Grid),it update on every click without any problem
so I assumed that the problem is comming from the focus changing when I navigate in the grid RV

from dpadrecyclerview.

rubensousa avatar rubensousa commented on August 18, 2024

@mohamedriadhzrig can you please upload a sample project that reproduces that issue? Are you sure that's a problem with DpadRecyclerView and not a bug somewhere else?

so I assumed that the problem is comming from the focus changing when I navigate in the grid RV

Focus changes shouldn't "mess" the grid unless you trigger adapter updates on item selection. Again, please upload a sample that showcases the problem so I can have a look

from dpadrecyclerview.

mohamedriadhzrig avatar mohamedriadhzrig commented on August 18, 2024
    rv is the grid RevycleView

private void setupMoviesRecyclerView()
{
moviesAdapter = new MoviesAdapter(new MovieComparator(), requestManager);
mainActivityViewModel = new ViewModelProvider(this).get(MovieViewModel.class);
initRecyclerviewAndAdapter();
}

private void initRecyclerviewAndAdapter()
{
rv = findViewById(R.id.rv);
rv.setOrientation(RecyclerView.VERTICAL);
if (Callback.isTvBox) rv.setFadingEdgeLength(110);
rv.setSmoothFocusChangesEnabled(false);
rv.setHasFixedSize(true);
rv.setAdapter(moviesAdapter.withLoadStateFooter(new LoadStateAdapter(v -> moviesAdapter.retry())));
}

private void recreate_data(int position)
{
mainActivityViewModel.moviePagingDataFlowable.subscribe(moviePagingData -> moviesAdapter.submitData(getLifecycle(),
moviePagingData));
}

public void setAdapterToCatListview()
{
adapter_category = new AdapterCategory(this, arrayListCat, (item, position) -> new Handler().postDelayed(() ->
recreate_data(position), 0));
rv_cat.setAdapter(adapter_category);
adapter_category.select(1);
pos = 1;
}

private void setupCategory()
{
arrayListCat = new ArrayList<>();
rv_cat.setItemAnimator(new DefaultItemAnimator());
rv_cat.setHasFixedSize(true);
getDataCat();
}

the only solution that make the Recycleview rv work fine is to use this before updating its data

rv.setSelectedPosition(0);

from dpadrecyclerview.

rubensousa avatar rubensousa commented on August 18, 2024

That code snippet has a couple of issues:

  1. Do not call setItemAnimator, specially if you're using the default item animator. DpadRecyclerView doesn't like custom animators that have changes enabled. Please remove that line.

  2. Looks like you're subscribing to the moviePagingDataFlowable multiple times. Please keep only one subscription active.

  3. I don't see a usage of OnViewHolderSelectedListener in the snippet above. How are you observing item selections? Please have a look here: https://rubensousa.github.io/DpadRecyclerView/selection/

from dpadrecyclerview.

mohamedriadhzrig avatar mohamedriadhzrig commented on August 18, 2024

hey again,I fixed it by updating this line
rv.setAdapter(moviesAdapter.withLoadStateFooter(new LoadStateAdapter(v -> moviesAdapter.retry())));
to
rv.setAdapter(moviesAdapter);

but when I update the recycleview(rv) the selection of the item jump to the last item of the new loaded item(14 per page)
so I have to add this
rv.setSelectedPosition(0);
to avoid hiding the 2 row
(even with that sometimes it jump to the last)

I'll share with you the activity and the adapter of rv

@androidentrypoint
public class MovieActivity extends AppCompatActivity {
private CategoryViewModel categoryViewModel;
private MovieViewModel movieViewModel;
private CategoryAdapter categoryAdapter;
private MoviesAdapter moviesAdapter;
private DpadRecyclerView rv_cat, rv;

@Inject
RequestManager requestManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setupOrientation();
    initViews();
    setupCategoryRecyclerView();
    setupMoviesRecyclerView();
}

private void setupOrientation() {
    if (Callback.isLandscape) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    IsStatusBar.ifSupported(this);
    IsScreenshot.ifSupported(this);
    IsRTL.ifSupported(this);
}

private void initViews() {
    setContentView(R.layout.activity_live_tv);
    findViewById(R.id.theme_bg).setBackgroundResource(R.drawable.bg_dark_panther);
    findViewById(R.id.iv_back_page).setOnClickListener(view -> onBackPressed());

    rv_cat = findViewById(R.id.rv_cat);
    rv_cat.setSelectedPosition(1);
    rv_cat.setHasFixedSize(true);

    TextView page_title = findViewById(R.id.tv_page_title);
    page_title.setText(getString(R.string.movies_home));
}

private void setupCategoryRecyclerView() {
    categoryAdapter = new CategoryAdapter(this, new ArrayList<>(), (item, position) -> {
        categoryAdapter.select(position);
        movieViewModel.setCategoryId(Callback.categoryId);
        rv.setSelectedPosition(0); 
        //because when I select a category, the selection jump to the last item of the first loaded page (14/page)
    });

    rv_cat.setAdapter(categoryAdapter);

    categoryViewModel = new ViewModelProvider(this, new CategoryViewModelFactory(
            new CategoryRepository(
                    MyApplication.getInstance().getAppDatabase().categoryDao(),
                    MyApplication.getInstance().getApiService()
            )
    )).get(CategoryViewModel.class);

    categoryViewModel.getAllCategoriesFromCache(CategoryType.MOVIE).observe(this, categories -> {
        Callback.categoryId = categories.get(0).getId();
        categories.add(0, new Category("", getString(R.string.favourite), getString(R.string.favourite), CategoryType.MOVIE));
        categoryAdapter.setCategories(categories);
        rv_cat.setSelectedPosition(1);
        observeMoviesData();
    });
}

private void observeMoviesData() {
    movieViewModel.getMovies().observe(this, pagingData -> moviesAdapter.submitData(getLifecycle(), pagingData));
    movieViewModel.setCategoryId(Callback.categoryId);
}

private void setupMoviesRecyclerView() {
    moviesAdapter = new MoviesAdapter(new MovieComparator(), requestManager);
    movieViewModel = new ViewModelProvider(this).get(MovieViewModel.class);
    initializeRecyclerView();
}

private void initializeRecyclerView() {
    rv = findViewById(R.id.rv);
    rv.setOrientation(RecyclerView.VERTICAL);
    if (Callback.isTvBox) rv.setFadingEdgeLength(110);
    rv.setSmoothFocusChangesEnabled(false);
    rv.setHasFixedSize(true);
    rv.setSpanCount(5);

// rv.setAdapter(moviesAdapter.withLoadStateFooter(new LoadStateAdapter(v -> moviesAdapter.retry()))); adding footer is // making the problem
rv.setAdapter(moviesAdapter);
}

private long lastDPadDownEventTime = 0;

@Override
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_DOWN && rv.hasFocus()) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_DOWN:
                if (System.currentTimeMillis() - lastDPadDownEventTime < 345) return true;
                lastDPadDownEventTime = System.currentTimeMillis();
                break;
            case KeyEvent.KEYCODE_BACK:
                onBackPressed();
                return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public void onBackPressed() {
    super.onBackPressed();
}

@Override
public void onDestroy() {
    super.onDestroy();
}

}

public class MoviesAdapter extends PagingDataAdapter<Movie, MoviesAdapter.MovieViewHolder> {
private static final int LOADING_ITEM = 0;
private static final int MOVIE_ITEM = 1;

private final int columnWidth;
private final int columnHeight;
private final RequestManager glide;

public MoviesAdapter(@NonNull DiffUtil.ItemCallback<Movie> diffCallback, RequestManager glide) {
    super(diffCallback);
    this.glide = glide;
    this.columnWidth = Callback.columnWidth;
    this.columnHeight = (int) (columnWidth * 1.15);
}

@NonNull
@Override
public MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new MovieViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie, parent, false));
}

@Override
public void onBindViewHolder(@NonNull MovieViewHolder holder, int position) {
    Movie movie = getItem(position);
    if (movie != null) {
        configureViewHolder(holder, movie);
    }
}

private void configureViewHolder(MovieViewHolder holder, Movie movie) {
    holder.tv_movie_title.setText(movie.getName());
    setMovieRating(holder, movie);
    setImage(holder, movie);

    holder.fd_movie_card.setOnFocusChangeListener((v, hasFocus) -> {
        float scale = hasFocus ? 1.1f : 1.0f;
        float alpha = hasFocus ? 1.0f : 0.5f;
        float elevation = hasFocus ? 50f : 0f;

        holder.itemView.animate()
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .scaleX(scale)
                .scaleY(scale)
                .setDuration(500)
                .start();

        holder.itemView.setAlpha(alpha);
        ViewCompat.setElevation(holder.itemView, elevation);
    });

    holder.fd_movie_card.setOnClickListener(view -> {
        animateClick(view);
        Intent intent = new Intent(view.getContext(), DetailsMovieActivity.class);
        intent.putExtra("movie_object", movie);
        view.getContext().startActivity(intent);
    });
}

private void setImage(MovieViewHolder holder, Movie movie) {
    try {
        glide.load(movie.getStreamIcon().isEmpty() ? "null" : movie.getStreamIcon())
                .thumbnail(glide.load(R.mipmap.ic_launcher))
                .into(holder.iv_movie);
    } catch (Exception e) {
        glide.load(R.mipmap.ic_launcher).into(holder.iv_movie);
    }
    holder.iv_movie.setScaleType(ImageView.ScaleType.CENTER_CROP);
    holder.iv_movie.setLayoutParams(new RelativeLayout.LayoutParams(columnWidth, columnHeight));
}

private void setMovieRating(MovieViewHolder holder, Movie movie) {
    if (movie.getRating().isEmpty()) {
        holder.tv_movie_rating.setVisibility(View.INVISIBLE);
    } else {
        String ratingText = movie.getRating().length() > 2 ? movie.getRating().substring(0, 3) : movie.getRating();
        holder.tv_movie_rating.setText(ratingText);
        holder.tv_movie_rating.setVisibility(View.VISIBLE);
    }
}

private void animateClick(View view) {
    view.animate().scaleX(1.1f).scaleY(1.1f).setDuration(100)
            .withEndAction(() -> view.animate().scaleX(1f).scaleY(1f).setDuration(100).start())
            .start();
}

@Override
public int getItemViewType(int position) {
    return position == getItemCount() ? MOVIE_ITEM : LOADING_ITEM;
}

public static class MovieViewHolder extends RecyclerView.ViewHolder {
    SimpleRoundedImageView iv_movie;
    TextView tv_movie_title, tv_movie_rating;
    View fd_movie_card;

    public MovieViewHolder(@NonNull View itemView) {
        super(itemView);
        iv_movie = itemView.findViewById(R.id.iv_movie);
        tv_movie_title = itemView.findViewById(R.id.tv_movie_title);
        tv_movie_rating = itemView.findViewById(R.id.tv_movie_rating);
        fd_movie_card = itemView.findViewById(R.id.fd_movie_card);
    }
}

}

from dpadrecyclerview.

rubensousa avatar rubensousa commented on August 18, 2024

Please upload this sample to a github repository that reproduces the issue you're describing. Alternatively, fork this repo and update its sample to showcase the issue. This really seems like an issue of misusing the adapter update mechanisms and triggering unnecessary selections.

from dpadrecyclerview.

rubensousa avatar rubensousa commented on August 18, 2024

@mohamedriadhzrig any update here?

from dpadrecyclerview.

mohamedriadhzrig avatar mohamedriadhzrig commented on August 18, 2024

@rubensousa I cannot share the code ,I already got in trouble sharing that activity and adapter...Anyway,I kind of find a solution,I'm not 100% convinced but I don't have choices,I have to scroll to a negative position before updating the list of the adapter

from dpadrecyclerview.

rubensousa avatar rubensousa commented on August 18, 2024

You shouldn't need to scroll to a negative position, and I'm not sure that the selection will be applied in that case. I'll close this issue since this seems like an user error. If you can find time to create a proper sample, feel free to comment.

from dpadrecyclerview.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.