Comments (10)
Hello @mohamedriadhzrig. You need to share more information, otherwise I can't help. What issue do you have exactly?
from dpadrecyclerview.
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.
@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.
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.
That code snippet has a couple of issues:
-
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. -
Looks like you're subscribing to the
moviePagingDataFlowable
multiple times. Please keep only one subscription active. -
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.
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.
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.
@mohamedriadhzrig any update here?
from dpadrecyclerview.
@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.
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)
- Add navigation sound when searching for new view
- Add support for long text scrolling
- Scroll jumps to the top on item's layout update HOT 7
- Scroll position start question HOT 14
- Nested vertical lists HOT 1
- Vertical list with focus centered HOT 2
- IndexOutOfBoundsException but I can't reproduce it. HOT 5
- Touch behavior in scrolling HOT 5
- help HOT 2
- Focus issue after touch event
- How to implement StaggeredGridLayout? HOT 5
- Update compose integration now that view-interop is fixed
- Allow skipping layout requests during scroll
- Expose ViewHolder focus state
- Add support for custom parent alignment based on ViewHolder position
- Add support for linear circular focus
- Gridrecyclerview with height 0.5 of the screen height - alignment problem (last row cut off) HOT 14
- First item of first row is smaller then all the others HOT 4
- Fast scrolling - loosing focus when having images from an url in the items HOT 21
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dpadrecyclerview.