Screen rotation with viewpager, tablelayout and fragments - android

I spend time to search an answer to my problem without success.
When i rotating my fragments are recreated inside viewpager adapter but not displayed, i don't no why ?
I have tried FragmentPagerStateAdapter instead of FragmentPagerAdapter but it doesn't work.
My activity code :
public class BookingsActivity extends BaseActivity implements ActivityCompat.OnRequestPermissionsResultCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener,LoginDialogFragment.LoginDialogFragmentListener, BookingsFragment.OnFragmentInteractionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bookings);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
.....
setupViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(BookingsFragment.newInstance(), "A venir");
adapter.addFragment(BookingsFragment.newInstance(), "Terminées");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<BookingsFragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public BookingsFragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(BookingsFragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
My fragment code :
public class BookingsFragment extends Fragment {
private ArrayList<Bookings> mBookings = new ArrayList<>();
private BookingCardAdapter adapter;
private RecyclerView recyclerView;
private LinearLayoutManager mLayoutManager;
private OnFragmentInteractionListener mListener;
private Location mLastLocation;
public BookingsFragment() {
// Required empty public constructor
}
public static BookingsFragment newInstance() {
BookingsFragment fragment = new BookingsFragment();
// Supply index input as an argument.
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_bookings, container, false);
// Inflate the layout for this fragment
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(this.getContext());
recyclerView.setLayoutManager(mLayoutManager);
adapter = new BookingCardAdapter(mBookings, this.getContext(), new BookingCardAdapter.BookingCardAdapterSubmitListener() {
#Override
public void onBookingClick(Bookings booking, int state) {
handleBookingClick(booking,state);
}
});
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public void setBookings(ArrayList<Bookings> bookings, int page) {
if (bookings != null && bookings.size() > 0) {
if (adapter != null) {
if (page == 1) {
mBookings.clear();
}
for (Bookings b : bookings) {
mBookings.add(b);
}
adapter.notifyDataSetChanged();
}
}
}
public void setLocation(Location location) {
if (location!=null) {
mLastLocation=location;
}
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}

Related

Dynamic update of a view (viewpager) for news application

I can not implement a data update of a Viewpager based fragment.
In fact I have a service that verifies and retrieves the latest information updates published online and comes to feed my database.
Once the job is finished I should update the screen but that's where I'm stuck.
I tried many techniques but until then I have not yet received to update the screen.
I am so overwhelmed by the subject that I do not have the right words.
Thanks for your help
My main activity
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
private static final String TAG = "MainActivity";
ViewPager viewPager;
TabLayout tabLayout;
DrawerLayout drawer;
NavigationView navigationView;
ActionBarDrawerToggle toggle;
Context mContext;
PagerAdapter vAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mContext = this;
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
reloadData();
}
private void setupViewPager(ViewPager viewPager) {
vAdapter = new PagerAdapter(getSupportFragmentManager());
vAdapter.addFragment(new StartFragment(), "START");
vAdapter.addFragment(new MapFragment(), "MAP");
vAdapter.addFragment(new ListArticle(), "ARTICLES");
viewPager.setAdapter(vAdapter);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.nav_profile:
startActivity(new Intent(mContext, ProfileActivity.class));
break;
case R.id.nav_map:
startActivity(new Intent(mContext, MapActivity.class));
break;
case R.id.nav_history:
startActivity(new Intent(mContext, HistoryActivity.class));
break;
case R.id.nav_help:
break;
default:
return false;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private void scheduleJobMatchDataUpdate(){
JobScheduler jobScheduler = (JobScheduler)getApplicationContext()
.getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName componentName = new ComponentName(this,
MatchUpdatedJob.class);
JobInfo jobInfo = null;
//if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
jobInfo = new JobInfo.Builder(1, componentName)
.setPeriodic(60000).setRequiredNetworkType(
JobInfo.NETWORK_TYPE_NOT_ROAMING)
.setPersisted(true).build();
// }
jobScheduler.schedule(jobInfo);
}
public void reloadData() {
scheduleJobMatchDataUpdate();
StartFragment fragment = new StartFragment();
if (fragment.isInLayout()) {
fragment.data();
}
}
}
//My PagerAdapter
public class PagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public PagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
public class StartFragment extends Fragment implements ArticleAdapter.ClickCB,
BaseSliderView.OnSliderClickListener, ViewPagerEx.OnPageChangeListener{
static final String TAG = "StartFragment";
public StartFragment() {
// Let empty
}
LinearLayoutManager mLayoutManager;
private SwipeRefreshLayout srl;
ArticleAdapter mAdapter;
Context mContext;
List<Article> mList;
List<Article> mListSelected = new ArrayList<>();
Call<List<Article>> call;
ApiService service;
RecyclerView rcv;
Bundle bundle;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mContext = getActivity();
this.mList = Article.findAll(this.mContext);
this.bundle = savedInstanceState;
service = RetrofitBuilder.createService(ApiService.class);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_start, container, false);
SliderLayout mSlider = (SliderLayout) view.findViewById(R.id.slider);
String[] imgUrl = new String[3];
imgUrl[0] = "http://...1.jpg";
imgUrl[1] = "http://...2.jpg";
imgUrl[2] = "http://...3.jpg";
for (String s: imgUrl){
MatchSliderView sliderView = new MatchSliderView(getContext());
sliderView
.image(s)
.description("...")
.setScaleType(BaseSliderView.ScaleType.Fit)
.setOnSliderClickListener(this);
sliderView.bundle(new Bundle());
sliderView.getBundle()
.putString("extra",s);
mSlider.addSlider(sliderView);
}
mSlider.setPresetTransformer(SliderLayout.Transformer.Accordion);
// mSlider.setPresetIndicator(SliderLayout.PresetIndicators.Center_Bottom);
mSlider.setCustomAnimation(new DescriptionAnimation());
mSlider.setDuration(5000);
mSlider.addOnPageChangeListener(this);
rcv = (RecyclerView) view.findViewById(R.id.rcv);
mLayoutManager = new LinearLayoutManager(MainApplication.getContext());
mLayoutManager.setOrientation(1);
rcv.setLayoutManager(mLayoutManager);
rcv.setHasFixedSize(true);
//mList = Article.findAll(this.mContext);
this.mAdapter = new ArticleAdapter(this.mContext,
StartFragment.this, mList, mListSelected);
rcv.setItemViewCacheSize(mList.size());
rcv.setAdapter(this.mAdapter);
Flubber.with()
.animation(Flubber.AnimationPreset.FADE_IN_UP)
.repeatCount(1)
.duration(2000)
.createFor(rcv)
.start();
srl = (SwipeRefreshLayout)view.findViewById(R.id.swipeRefreshLayout);
srl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
onItemsLoadComplete();
}
});
return view;
}
void onItemsLoadComplete() {
loadData();
srl.setRefreshing(false);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
#Override
public void onSliderClick(BaseSliderView slider) {
Toast.makeText(mContext, slider.getmTitle(),
Toast.LENGTH_SHORT).show();
}
#Override
public void removeNotify(Selection selection) {
badgeView.decrement();
}
public void loadData(){
try{
call = service.matchs();
call.enqueue(new Callback<List<Article>>() {
#Override
public void onResponse(Call<List<Article>> call, Response<List<Article>> response) {
if(response.isSuccessful()){
Article.deleteAll(mContext);
Article.saveAll(mContext,response.body());
}else{
Toast.makeText(mContext, "Update failed!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<List<Article>> call, Throwable t) {
call.isCanceled();
t.printStackTrace();
}
});
}catch (Exception e){
e.printStackTrace();
Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void refreshData(){
mList.clear();
mList.addAll(Article.findAll(this.mContext));
mAdapter.swap((ArrayList<Article>)mList);
}
#Override
public void onPause() {
super.onPause();
if (srl!=null) {
srl.setRefreshing(false);
srl.destroyDrawingCache();
srl.clearAnimation();
}
}
}
public class ArticleAdapter extends RecyclerView.Adapter<ArticleAdapter.ViewHolder> implements Filterable {
private Context mContext;
private static final String LOG_TAG = ArticleAdapter.class.getSimpleName();
List<Article> mListArticles = new ArrayList<>();
private List<Article> articleList;
private List<Article> articleListFiltered;
private ArticlesAdapterListener listener;
public ArticleAdapter(Context context, List<Article> mListItems){
this.mContext = context;
//this.mListArticles = mListItems;
if (mListArticles != null) {
mListArticles.clear();
mListArticles.addAll(mListItems);
}
else {
this.mListArticles = mListItems;
}
notifyDataSetChanged();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_article, parent, false);
return new ViewHolder(mContext, mListArticles, view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Article item = mListArticles.get(position);
holder.title.setText(Html.fromHtml( " " + item.getTitre()));
//Glide.with(this).load(item.getMedia()).into((ImageView) findViewById(R.id.media));
if(item.getMedia() != null && item.getMedia().length() >10) {
Picasso.with(mContext).load(item.getMedia()).into(holder.img);
}
}
#Override
public int getItemCount() {
return mListArticles.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
articleListFiltered = articleList;
} else {
List<Article> filteredList = new ArrayList<>();
for (Article row : articleList) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.getTitre().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(row);
}
}
articleListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = articleListFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
articleListFiltered = (ArrayList<Article>) results.values;
notifyDataSetChanged();
}
};
}
public static class ViewHolder extends RecyclerView.ViewHolder{
private Context mContext;
private List<Article> mItems;
public TextView title;
public ImageView img;
public ViewHolder(Context context, List<Article> newsList, View view){
super(view);
this.mContext = context;
this.mItems = newsList;
this.title= (TextView)view.findViewById(R.id.title);
this.img= (ImageView) view.findViewById(R.id.media);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ArticleDetailActivity.class);
intent.putExtra("id", mItems.get(getAdapterPosition()).getId());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
});
}
}
public interface ArticlesAdapterListener {
void onArticleSelected(Article article);
}
}
public class PagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public PagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
mAdapter.swap((ArrayList<Article>)mList);
mAdapter.notifyDataSetChanged();

Refresh Fragment View on Tab Change

Hello I'm implementing a dynamic TabLayout using a single fragment, i have manage to create the tabs so far but there is a problem using a single fragment. When im changing the tabs the fragment view is not updating repeatedly, although im updating the data in the fragment's onCreateView method based on the tab selection. I have a recyclerview in the that fragment which should change according to the tab selection. SO can anyone help me with it or do anyone have a better way of approach?
TabView Activity
public class SubCategory extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
Activity a;
String url;
List<CategoryEncapsulation> categories = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub_category);
a=this;
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
categories=((MyshinzGlobal)getApplicationContext()).getCategoryList();
setupViewPager(viewPager);
((MyshinzGlobal)getApplicationContext()).setCategory_id(categories.get(0).getCategory_id());
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
try {
for (int i = 0; i < categories.size(); i++) {
try {
adapter.addFragment(new ListFragment(), categories.get(i).getCategory_name());
} catch (Exception e) {
e.printStackTrace();
}
}
}catch (Exception e) {
e.printStackTrace();
}
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
((MyshinzGlobal)getApplicationContext()).setCategory_id(categories.get(position).getCategory_id());
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
Fragment class
public class ListFragment extends Fragment{
String category_id;
Activity a;
RecyclerView rv;
SubCategoryAdapter sca;
List<ParentListItem> parentListItems;
List<CategoryEncapsulation> categories = new ArrayList<>();
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.sub_category_fragment, container, false);
a=getActivity();
categories=((MyshinzGlobal)a.getApplicationContext()).getCategoryList();
category_id=((MyshinzGlobal)a.getApplicationContext()).getCategory_id();
parentListItems= new ArrayList<>();
Toast.makeText(getActivity(), String.valueOf(category_id), Toast.LENGTH_SHORT).show();
rv= (RecyclerView) view.findViewById(R.id.recycler_view);
for (int i=0; i<categories.size();i++){
if(categories.get(i).getCategory_id().equals(category_id)){
parentListItems=categories.get(i).getParentListItems();
}
}
sca=new SubCategoryAdapter(a,parentListItems);
rv.setAdapter(sca);
rv.setLayoutManager(new LinearLayoutManager(a));
//new GetAllSubCategoryTask(a,url,"1001").execute();
return view;
}
}
I have two solution for this.
1) make your view pager offset limit 0. Which default 1. If you are switching another fragment which not in offset, that fragment re-creating.
viewPager.setOffscreenPageLimit(0);
2) Tell your adapter, fragment has been changed. So your adapter will re-create its views again.
rv.notifyDataSetChanged();
I hope these will solve your problem.
First thing as you are using ViewPager, onCreateView() of Fragment will be called only when getItem() of FragmentPagerAdapter will be called.
If need to create a method in Fragment which will call RecyclerView.notifyDataSetChanged().
Check out updated code for both classes
TabView Activity
public class SubCategory extends AppCompatActivity {
//....
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
}
private void setupViewPager(ViewPager viewPager) {
//...
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
((MyshinzGlobal)getApplicationContext()).setCategory_id(categories.get(position).getCategory_id());
adapter.getItem(position).listUpdated();
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<ListFragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public ListFragment getItem(int position) {
return mFragmentList.get(position);
}
//...
}
}
Fragment class
public class ListFragment extends Fragment {
//...
public void listUpdated() {
for (int i = 0; i < categories.size(); i++) {
if (categories.get(i).getCategory_id().equals(category_id)) {
parentListItems.clear();
parentListItems.addAll(categories.get(i).getParentListItems());
}
}
sca.notifyDataSetChanged();
}
}

RecyclerView.Adapter onClick

I am having trouble implementing view.OnClickListener in my RecyclerView.Adapter. I am trying to implement multi-pane layout (landscape tablet layout version with RecyclerView and detail side by side). I have so far created this Activity:
public class MovieListActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
MovieListFragment movieListFragment = new MovieListFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.recycler_view_fragment, movieListFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
which starts a Fragment:
public class MovieListFragment extends Fragment {
#BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private MoviesAdapter mAdapter;
public MovieListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MoviesAdapter(getContext());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_movie_list, container, false);
ButterKnife.bind(this,view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.setAdapter(mAdapter);
return view;
}
#Override
public void onStart() {
super.onStart();
getPopularMovies();
}
private void getPopularMovies() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
MoviesApiService service = restAdapter.create(MoviesApiService.class);
service.getPopularMovies(new Callback<Movie.MovieResult>() {
#Override
public void success(Movie.MovieResult movieResult, Response response) {
mAdapter.setMovieList(movieResult.getResults());
}
#Override
public void failure(RetrofitError error) { error.printStackTrace(); }
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
}
which calls the RecyclerView.Adapter:
public class MoviesAdapter extends RecyclerView.Adapter<MovieViewHolder> {
private List<Movie> mMovieList;
private LayoutInflater mInflater;
private Context mContext;
public MoviesAdapter(Context context) {
this.mContext = context;
this.mInflater = LayoutInflater.from(context); //
}
#Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
View view = mInflater.inflate(R.layout.movie_row_item, parent, false);
final MovieViewHolder viewHolder = new MovieViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = viewHolder.getAdapterPosition();
Intent intent = new Intent(mContext, MovieDetailActivity.class);
intent.putExtra(MovieDetailActivity.MOVIE_EXTRA, mMovieList.get(position));
mContext.startActivity(intent);
}
});
return viewHolder;
}
#Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
Movie movie = mMovieList.get(position);
Picasso.with(mContext)
.load(movie.getPoster())
.placeholder(R.color.colorAccent)
.into(holder.thumbnail);
holder.movieTitle.setText(movie.getTitle());
holder.rating.setText(movie.getRating());
}
#Override
public int getItemCount() {
return (mMovieList == null) ? 0 : mMovieList.size();
}
public void setMovieList(List<Movie> movieList) {
this.mMovieList = new ArrayList<>();
this.mMovieList.addAll(movieList);
notifyDataSetChanged();
}
}
Here in onClick I need to decide whether to start a new Activity (like in my code) or update content of detail Fragment (in my tablet landscape layout).
According to this link, you should decide based on fact if your DetailFragment is != null in activity like this:
public void onItemSelected(int position) {
DisplayFragment displayFrag = (DisplayFragment) getFragmentManager()
.findFragmentById(R.id.display_frag);
if (displayFrag == null) {
// DisplayFragment (Fragment B) is not in the layout (handset layout),
// so start DisplayActivity (Activity B)
// and pass it the info about the selected item
Intent intent = new Intent(this, DisplayActivity.class);
intent.putExtra("position", position);
startActivity(intent);
} else {
// DisplayFragment (Fragment B) is in the layout (tablet layout),
// so tell the fragment to update
displayFrag.updateContent(position);
}
}
But I'm not able to check this in Adapter. Any help would be highly appreciated!
Thank you.
Created the custom interface click action to get the control in fragment class
i hope it will works for you
public class MoviesAdapter extends RecyclerView.Adapter {
MoviesAdapterCallback moviesAdapterCallback;
private List<Movie> mMovieList;
private LayoutInflater mInflater;
private Context mContext;
public MoviesAdapter(Context context,MoviesAdapterCallback moviesAdapterCallback) {
this.mContext = context;
this.moviesAdapterCallback =moviesAdapterCallback;
this.mInflater = LayoutInflater.from(context); //
}
#Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
View view = mInflater.inflate(R.layout.movie_row_item, parent, false);
final MovieViewHolder viewHolder = new MovieViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
/* int position = viewHolder.getAdapterPosition();
Intent intent = new Intent(mContext, MovieDetailActivity.class);
intent.putExtra(MovieDetailActivity.MOVIE_EXTRA, mMovieList.get(position));
mContext.startActivity(intent);
*/ moviesAdapterCallback.MovieClicked(view);
}
});
return viewHolder;
}
#Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
Movie movie = mMovieList.get(position);
Picasso.with(mContext)
.load(movie.getPoster())
.placeholder(R.color.colorAccent)
.into(holder.thumbnail);
holder.movieTitle.setText(movie.getTitle());
holder.rating.setText(movie.getRating());
}
#Override
public int getItemCount() {
return (mMovieList == null) ? 0 : mMovieList.size();
}
public void setMovieList(List<Movie> movieList) {
this.mMovieList = new ArrayList<>();
this.mMovieList.addAll(movieList);
notifyDataSetChanged();
}
public interface MoviesAdapterCallback {
void MovieClicked(View view);
}
}
in Fragment Class
public class MovieListFragment extends Fragment {
#BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private MoviesAdapter mAdapter;
public MovieListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_movie_list, container, false);
ButterKnife.bind(this,view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mAdapter = new MoviesAdapter(getContext(), new MoviesAdapter.MoviesAdapterCallback(){
#Override
public void MovieClicked(View view) {
DisplayFragment displayFrag = (DisplayFragment) getFragmentManager()
.findFragmentById(R.id.display_frag);
if (displayFrag == null) {
// DisplayFragment (Fragment B) is not in the layout (handset layout),
// so start DisplayActivity (Activity B)
// and pass it the info about the selected item
Intent intent = new Intent(this, DisplayActivity.class);
intent.putExtra("position", position);
startActivity(intent);
} else {
// DisplayFragment (Fragment B) is in the layout (tablet layout),
// so tell the fragment to update
displayFrag.updateContent(position);
}
}
});
mRecyclerView.setAdapter(mAdapter);
return view;
}
#Override
public void onStart() {
super.onStart();
getPopularMovies();
}
private void getPopularMovies() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
MoviesApiService service = restAdapter.create(MoviesApiService.class);
service.getPopularMovies(new Callback<Movie.MovieResult>() {
#Override
public void success(Movie.MovieResult movieResult, Response response) {
mAdapter.setMovieList(movieResult.getResults());
}
#Override
public void failure(RetrofitError error) { error.printStackTrace(); }
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
}

Android TabLayout with two tabs and a recyclerview in each scrolls to top when switching

I have an Activity with a TabLayout and a Viewpager that contains two tabs. These tabs are one Fragment that is reused which contains a Recyclerview. So each Fragment/Tab contains a recyclerview with a bunch of item.
When switching between these tabs the scroll state isn't retained when I go back to the previous tab.
What am I missing?
Activity:
public class EventsActivity extends AbstractTracActivity implements OnRowClickListener {
#BindView(R.id.toolbar)
Toolbar toolbar;
#BindView(R.id.tabs)
TabLayout tabLayout;
#BindView(R.id.viewpager)
ViewPager viewPager;
private final String TAG = EventsActivity.class.getSimpleName();
private static Context context;
private SearchView searchView;
private static EventListFragment eventsFragment, clubsFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.TracTracAppTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.events);
ButterKnife.bind(this);
context = this;
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setLogo(R.drawable.tractrac_logo);
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
eventsFragment = EventListFragment.newInstance(EventListFragment.ListType.EVENTS);
clubsFragment = EventListFragment.newInstance(EventListFragment.ListType.CLUBS);
TabLayout.Tab events = tabLayout.newTab();
TabLayout.Tab clubs = tabLayout.newTab();
tabLayout.addTab(events, 0);
tabLayout.addTab(clubs, 1);
tabLayout.setTabTextColors(ContextCompat.getColorStateList(this, R.color.accent));
tabLayout.setSelectedTabIndicatorColor(ContextCompat.getColor(this, R.color.accent));
ViewPagerAdapter adapter = new ViewPagerAdapter (getSupportFragmentManager());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.setOffscreenPageLimit(2);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
#Override
public void onPageSelected(int position) { }
#Override
public void onPageScrollStateChanged(int state) {
searchView.setQuery("", true);
searchView.clearFocus();
searchView.setIconified(true);
eventsFragment.filterList(null);
clubsFragment.filterList(null);
}
});
}
...
public static class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 1:
return clubsFragment;
default:
return eventsFragment;
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 1:
return context.getResources().getString(R.string.section_clubs);
default:
return context.getResources().getString(R.string.section_events);
}
}
}
}
Fragment:
public class EventListFragment extends Fragment implements EventsFragmentPresenter.ViewInterface {
enum ListType { EVENTS, CLUBS }
private EventsFragmentPresenter presenter;
private ListType listType;
private List<Event> events;
private RecyclerView recyclerView;
public static EventListFragment newInstance(ListType listType) {
EventListFragment f = new EventListFragment();
Bundle args = new Bundle();
args.putSerializable("listType", listType);
f.setArguments(args);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(com.tractrac.androidlib.R.layout.base_list_fragment, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = (RecyclerView) view.findViewById(com.tractrac.androidlib.R.id.recycler_view);
switch (getListType()) {
case EVENTS:
getPresenter().getEvents();
break;
case CLUBS:
getPresenter().getClubEvents();
break;
}
}
private EventsFragmentPresenter getPresenter() {
if (presenter == null) {
presenter = new EventsFragmentPresenter();
presenter.initialize(this);
}
return presenter;
}
private ListType getListType() {
if (listType == null) {
listType = (ListType) getArguments().getSerializable("listType");
}
return listType;
}
#Override
public void listReady(List<Event> events) {
EventsRecyclerAdapter adapter = new EventsRecyclerAdapter(events, (EventsActivity) getActivity());
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
if (getListType() == ListType.EVENTS) {
mLayoutManager.scrollToPosition(getPresenter().getCurrentDayEventIndex(events));
}
this.events = events;
((EventsActivity) getActivity()).hideSpinner();
}
public void filterList(String filterBy) {
if (TextUtils.isEmpty(filterBy)) {
EventsRecyclerAdapter adapter = new EventsRecyclerAdapter(events, (EventsActivity) getActivity());
recyclerView.setAdapter(adapter);
return;
}
List<Event> filteredEvents = new ArrayList<>();
for (Event event : events) {
if (event.getName().toLowerCase().contains(filterBy) || event.getLocation().toLowerCase().contains(filterBy))
filteredEvents.add(event);
}
EventsRecyclerAdapter adapter = new EventsRecyclerAdapter(filteredEvents, (EventsActivity) getActivity());
recyclerView.setAdapter(adapter);
}
}
In onPageScrollStateChanged you are calling filterList where you are creating a new EventsRecyclerAdaptereach time which is the cause of scroll state being reset.
You should set the adapter once to your RecyclerView and later call notify methods.

Same fragment with different contents in viewpager

I have one parent fragment where there is viewpager and tablayout.
Viewpager holds the fragment with different contents associated with it.
Every think works fine on swipe but whenever I tap on the different tabs of the tablayout, categoryId and categoryName of SwipableFragment is changed to adjacent tab's SwipableFragmet to the visible fragment.
Basically when I launch my FragmentAllNews (containing a ViewPager) it's shown the second fragment/page instead of the first and when I swipe to the second I see the third... In other words It's always shown the next or the previous fragment/page depending on the swipe direction (left or right).
Sorry For my bad english :(
here are my Fragments and FragmentStatePagerAdater class
###1 FragmentAllNews which holds the viewpager and tablayout
public class FragmentAllNews extends Fragment {
#Bind(R.id.tab_layout)
TabLayout tabLayout;
#Bind(R.id.all_news_viewpager)
ViewPager viewPager;
SessionManager sessionManager;
String categoryId;
String categoryName;
ArrayList<TabModel> tabs;
public static FragmentAllNews createNewInstance() {
FragmentAllNews fragmentAllNews = new FragmentAllNews();
return fragmentAllNews;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sessionManager = new SessionManager(getActivity());
tabs = sessionManager.getSwitchedNewsValue() == 0 ?
StaticStorage.getTabData(0) :
StaticStorage.getTabData(1);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.fragment_all_news, container, false);
ButterKnife.bind(this, fragmentView);
return fragmentView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setViewPager(tabs);
setTabLayout();
}
private void setTabLayout() {
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void setViewPager(ArrayList<TabModel> tabs) {
ArrayList<NewsFragmentModel> frags = new ArrayList<>();
for (int i = 0; i < tabs.size(); i++) {
if (i == 0) {
categoryId = tabs.get(i).cat_id;
categoryName = tabs.get(i).cat_name;
frags.add(new NewsFragmentModel(FragmentBreakingAndLatestNews.createNewInstance(categoryId, categoryName), categoryName));
} else {
categoryId = tabs.get(i).cat_id;
categoryName = tabs.get(i).cat_name;
frags.add(new NewsFragmentModel(SwipableFragment.createNewInstance(categoryId, categoryName), categoryName));
}
}
NewsPagerAdapter adapter = new NewsPagerAdapter(getChildFragmentManager(),frags);
viewPager.setAdapter(adapter);
}
#Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
}
###2 SwipableFragment which the fragment attached to the viewpager
public class SwipableFragment extends Fragment implements NewsTitlesAdapter.RecyclerPositionListener {
#Bind(R.id.recycler_view)
RecyclerView recyclerView;
#Bind(R.id.progess)
ProgressBar progressBar;
#Bind(R.id.cat_id)
TextView categoryTextView;
ArrayList<NewsObj> newsObjs;
NewsTitlesAdapter newsTitlesAdapter;
SessionManager sessionManager;
private static String categoryId;
private static String categoryName;
public static SwipableFragment createNewInstance(String category_id, String category_name) {
SwipableFragment swipableFragment = new SwipableFragment();
Bundle box = new Bundle();
box.putString(StaticStorage.NEWS_CATEGORY_ID, category_id);
box.putString(StaticStorage.NEWS_CATEGORY, category_name);
swipableFragment.setArguments(box);
return swipableFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sessionManager = new SessionManager(getActivity());
categoryId = getArguments().getString(StaticStorage.NEWS_CATEGORY_ID);
categoryName = getArguments().getString(StaticStorage.NEWS_CATEGORY);
newsObjs = (sessionManager.getSwitchedNewsValue() == 0) ?
NewsData.getNewsRepublica(getActivity()) :
NewsData.getNewsNagarik(getActivity(),categoryName);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_swipable, container, false);
ButterKnife.bind(this, view);
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i("category", categoryId + " " + categoryName);
categoryTextView.setText(categoryId+" "+categoryName);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new DefaultItemAnimator());
newsTitlesAdapter = new NewsTitlesAdapter(newsObjs);
newsTitlesAdapter.setOnRecyclerPositionListener(this);
recyclerView.setAdapter(newsTitlesAdapter);
recyclerView.addOnScrollListener(new EndlessScrollListener(linearLayoutManager) {
#Override
public void onLoadMore(int current_page) {
Log.i("categoryId", categoryId+" "+categoryName);
categoryTextView.setText(categoryId+" "+categoryName);
progressBar.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
ArrayList<NewsObj> moreNews = sessionManager.getSwitchedNewsValue() == 0 ?
NewsData.getNewsRepublica(getContext()) :
NewsData.getNewsNagarik(getContext(),categoryName);
int curSize = newsTitlesAdapter.getItemCount();
newsObjs.addAll(moreNews);
newsTitlesAdapter.notifyItemRangeInserted(curSize, newsObjs.size() - 1);
progressBar.setVisibility(View.GONE);
}
}, 5000);
}
});
}
#Override
public void onChildItemPositionListen(int position, View view) {
if (view.getId() == R.id.news_share_text_view) {
} else if (view.getId() == R.id.news_show_detail_text_view) {
} else {
Intent newsDetailIntent = new Intent(getActivity(), NewsDetailActivity.class);
NewsObj newsObj = newsObjs.get(position);
newsObj.setNewsCategory(categoryName);
newsDetailIntent.putExtra(NewsDetailActivity.NEWS_TITLE_EXTRA_STRING, newsObj);
startActivity(newsDetailIntent);
}
}
}
###3 NewsPagerAdapter is the subclass extended from FragmentStatePagerAdapter
public class NewsPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<NewsFragmentModel> frags;
public NewsPagerAdapter(FragmentManager fm) {
super(fm);
}
public NewsPagerAdapter(FragmentManager fm,ArrayList<NewsFragmentModel> frags){
super(fm);
this.frags = frags;
}
#Override
public Fragment getItem(int position) {
return frags.get(position).getFrag();
}
#Override
public int getCount() {
return frags.size();
}
#Override
public CharSequence getPageTitle(int position) {
return frags.get(position).getTitle();
}
}
###4 NewsFragmentModel
public class NewsFragmentModel {
private Fragment frag;
private String title;
public NewsFragmentModel(Fragment frag, String title) {
this.frag = frag;
this.title = title;
}
public Fragment getFrag() {
return frag;
}
public void setFrag(Fragment frag) {
this.frag = frag;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Am I doing any mistakes ? please help me.If you need more info please let me know. My final hope is Stackoverflow

Categories

Resources