Unable to restore RecyclerView's position/state - android

Whenever I move from DetailsActivity to MainActivity the RecyclerView is reset and list is always shown from the top position.
Full source code can be seen here. The code is still largely a work in progress.
MainActivityFragment is as follows.
public class MainActivityFragment extends Fragment {
private ArrayList<Movie> mMovieArrayList = new ArrayList<Movie>();
private static final String PAGE = "1";
private RecyclerView mRecyclerView;
private SharedPreferences mSettings;
private SharedPreferences.Editor mEditor;
private static final String LOG = MainActivityFragment.class.getSimpleName();
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_movie_list, container, false);
// Set column size to 2 for default and portrait
// and 3 for landscape orientations
int column = Integer.parseInt(getString(R.string.grid_portrait));
if (getResources().getConfiguration().orientation == 1) {
column = Integer.parseInt(getString(R.string.grid_portrait));
} else if (getResources().getConfiguration().orientation == 2) {
column = Integer.parseInt(getString(R.string.grid_landscape));
}
if (getActivity().findViewById(R.id.movie_detail_container) != null) {
column = Integer.parseInt("2");
}
mSettings = PreferenceManager.getDefaultSharedPreferences(getActivity());
mEditor = mSettings.edit();
mEditor.apply();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), column));
mRecyclerView.setAdapter(new MovieAdapter(getActivity(), mMovieArrayList));
return rootView;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onStart() {
super.onStart();
updateMovieList();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main_fragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.popularity:
mEditor.putString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_popularity));
mEditor.apply();
updateMovieList();
item.setChecked(true);
Log.d(LOG, "onOptionsItemSelected: popularity");
return true;
case R.id.rating:
mEditor.putString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_top_rated));
mEditor.apply();
updateMovieList();
item.setChecked(true);
Log.d(LOG, "onOptionsItemSelected: rating");
return true;
case R.id.favorite:
mEditor.putString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_favorite));
mEditor.apply();
updateMovieList();
item.setChecked(true);
Log.d(LOG, "onOptionsItemSelected: favorite");
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
String sortBy = mSettings.getString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_popularity));
if (sortBy.equals(getResources().getString(R.string.url_popularity))) {
menu.findItem(R.id.popularity).setChecked(true);
} else if (sortBy.equals(getResources().getString(R.string.url_top_rated))) {
menu.findItem(R.id.rating).setChecked(true);
} else if (sortBy.equals(getResources().getString(R.string.url_favorite))) {
menu.findItem(R.id.favorite).setChecked(true);
}
}
private void updateMovieList() {
mMovieArrayList = new ArrayList<>();
String sortBy = mSettings.getString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_popularity));
if (sortBy.equals(getResources().getString(R.string.url_popularity)) ||
sortBy.equals(getResources().getString(R.string.url_top_rated))) {
try {
mMovieArrayList =
new FetchMoviesTask().execute(sortBy, PAGE).get();
} catch (ExecutionException | InterruptedException ei) {
ei.printStackTrace();
}
} else if (sortBy.equals(getResources().getString(R.string.url_favorite))) {
ContentResolver resolver = getActivity().getContentResolver();
Cursor cursor =
resolver.query(MovieContract.MovieEntry.CONTENT_URI,
null,
null,
null,
null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
String title = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.TITLE));
String movie_id = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.MOVIE_ID));
String poster = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.POSTER));
String backdrop = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.BACKDROP));
String overview = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.OVERVIEW));
String vote_average = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.VOTE_AVERAGE));
String release_date = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.DATE));
Movie movie = new Movie(title, release_date, poster,
vote_average, overview, backdrop, movie_id);
mMovieArrayList.add(movie);
} while (cursor.moveToNext());
}
}
if (cursor != null)
cursor.close();
}
mRecyclerView.setAdapter(new MovieAdapter(getActivity(), mMovieArrayList));
mRecyclerView.getAdapter().notifyDataSetChanged();
}
}
MainActivity is as follows.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
// if (id == android.R.id.home) {
// onBackPressed();
// return true;
// }
return super.onOptionsItemSelected(item);
}
}
I have tried setting saving up RecyclerView's state like shown in this post.
I have also tried saving the mArrayList in onSaveInstanceState and restoring it in onActivityCreated or onViewCreated like in this post.
Both of these have not worked for me. As soon as I return back from the DetailsActivity to MainActivity the position is gone.
Thanks.

You're calling a method to update movies list in onStart callback of fragment life cycle. Which means when your main activity is shown back, you're resetting your list. You shouldn't.
You set a new instance of adapter at the end of update list method. That redraws the entire list. You should rethink your life cycles. Call update movie list only in onCreate or onCreateView and always check if adapter opject is null and only then use setAdapter method on recycler view. If adapter is not null, just call notifyDataSetChanged or whatever is needed to update your items.

Maybe this could help. Eventhough it will scroll all the way to the selected item each time.

Related

How is to implement action mode in fragment in androidx?

I have to implement action mode in fragment, but its gets nullpointer exception in action mode. I have tried so much but not gets any results, Please help me I am new in android. I have also tried startActionMode but not impact. I have wasted my time & searched lot of code not found any solution. Please help me
public class GalleryFragment extends Fragment {
private GalleryViewModel galleryViewModel;
private ActionModeCallback actionModeCallback;
private ActionMode actionMode;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
galleryViewModel =
ViewModelProviders.of(this).get(GalleryViewModel.class);
View root = inflater.inflate(R.layout.fragment_gallery, container, false);
final TextView textView = root.findViewById(R.id.text_gallery);
galleryViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
final Button btnLoad = root.findViewById(R.id.load);
btnLoad.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
enableActionMode(1, true );
}
});
return root;
}
public void enableActionMode(int position, boolean bool) {
int count = 4;
if(actionMode == null) {
actionMode = ((AppCompatActivity)getActivity()).startSupportActionMode(actionModeCallback);
}
if (count == 0) {
actionMode.finish();
actionMode = null;
} else {
actionMode.setTitle(String.valueOf(count));
actionMode.invalidate();
}
}
private class ActionModeCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.actionbar_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// getSupportActionBar().hide();
menu.findItem(R.id.action_delete).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Log.d("API123", ""+item.getItemId());
switch (item.getItemId()) {
case R.id.action_delete:
// delete all the selected rows
//mode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
//clear selections
mode.finish();
actionMode = null;
}
}
}
This is mycode, null pointer in actionmode. please help me i wasting my time. searching lot of, no result found

Implement Searchview with Navigation Drawer and Fragment inside

I want to implement SearchView on the toolbar in Navigation-Drawer and there is Fragment Activity like in the picture. I've tried SearchView on regular Activity and I succeeded, but when I implement it to Fragment Activity, why its code can not run.
This is my Main Activity.java
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
public static final String MAKAN = "makanan";
public static String WHERE = "makanan";
public static int WHERE2;
String mQuery;
ArrayList<Makanan> mlist = new ArrayList<>();
ArrayList<Makanan> mlistAll = new ArrayList<>();
public String mQuery2;
boolean isFiltered;
MakananAdapter mAdapter;
ArrayList<Integer> mListMapFilter = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View header = ((NavigationView)findViewById(R.id.nav_view)).getHeaderView(0);
ImageButton ib = (ImageButton)header.findViewById(R.id.imageButton);
ib.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MapsActivity.class);
startActivity(intent);
}
});
setTitle("Beranda");
Hal1 fragment = new Hal1();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragment, "fragment1");
//WHERE = "11";
fragmentTransaction.commit();
}
#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 onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
setTitle("About");
Hal2 fragments = new Hal2();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragments, "fragment1");
fragmentTransaction.commit();
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.frag_all) {
setTitle("Rekomendasi");
SecondFragment fragment = new SecondFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragment, "fragment1");
WHERE = "11";
fragmentTransaction.commit();
} ...
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}}
And My SecondFragment.java
public class SecondFragment extends Fragment implements MakananAdapter.IMakananAdapter, SearchView.OnQueryTextListener {
public static final String MAKAN = "makanan";
private AppCompatActivity compat;
private RecyclerView recyclerView;
private MakananAdapter adapter;
public SecondFragment() {
// Required empty public constructor
}
ArrayList<Makanan> mList = new ArrayList<>();
//MakananAdapter mAdapter;
String mQuery;
ArrayList<Makanan> mlist = new ArrayList<>();
ArrayList<Makanan> mlistAll = new ArrayList<>();
boolean isFiltered;
MakananAdapter mAdapter;
ArrayList<Integer> mListMapFilter = new ArrayList<>();
private SearchView searchView = null;
private SearchView.OnQueryTextListener queryTextListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.activity_calling, container, false);
recyclerView = (RecyclerView) rootview.findViewById(R.id.recyclerView);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 2);
recyclerView .setHasFixedSize(true);
recyclerView .setItemAnimator(new DefaultItemAnimator());
recyclerView .setLayoutManager(gridLayoutManager);
recyclerView.setLayoutManager(gridLayoutManager);
adapter = new MakananAdapter(mList);
recyclerView.setAdapter(adapter);
return rootview;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
fillData1();
//if i use this call method, the function is work
//[enter image description here][1]doFilter("roker");
}
private void fillData1() {
Resources resources = getResources();
String[] arJudul = resources.getStringArray(R.array.recommend);
String[] arDeskripsi = resources.getStringArray(R.array.recommend_desc);
String[] arHarga = resources.getStringArray(R.array.recommend_price);
String[] arDetail = resources.getStringArray(R.array.recommend_details);
String[] arLokasi = resources.getStringArray(R.array.recommend_locations);
String[] arLat = resources.getStringArray(R.array.recommend_lat);
String[] arLng = resources.getStringArray(R.array.recommend_longi);
TypedArray a = resources.obtainTypedArray(R.array.recommend_pict);
String[] arFoto = new String[a.length()];
for (int i = 0; i < arFoto.length; i++) {
int id = a.getResourceId(i, 0);
arFoto[i] = ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ resources.getResourcePackageName(id) + '/'
+ resources.getResourceTypeName(id) + '/'
+ resources.getResourceEntryName(id) + '/';
}
a.recycle();
for (int i = 0; i < arJudul.length; i++) {
mList.add(new Makanan(arJudul[i], arDeskripsi[i], arFoto[i], arHarga[i], arDetail[i], arLokasi[i], arLat[i], arLng[i]));
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setQueryHint("Cari");
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
//Log.i("onQueryTextSubmit", query);
//mQuery = query.toLowerCase();
//doFilter(mQuery);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
Log.i("onQueryTextChange", newText);
mQuery = newText.toLowerCase();
doFilter(mQuery);
return true;
}
});
return;
}
//My filter function goes here
public boolean doFilter(String query) {
if (!isFiltered) {
mlistAll.clear();
mlistAll.addAll(mList);
isFiltered = true;
}
mList.clear();
if (query.isEmpty()) {
mList.addAll(mlistAll);
isFiltered = false;
return false;
} else {
mListMapFilter.clear();
for (int i = 0; i < mlistAll.size(); i++) {
Makanan makanan = mlistAll.get(i);
if (makanan.judul.toLowerCase().contains(query) ||
makanan.deskripsi.toLowerCase().contains(query)) {
mList.add(makanan);
mListMapFilter.add(i);
}
}
return true;
}
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return true;
}
#Override
public void doClick(int pos) {
Intent intent = new Intent(getContext(), DetailActivity.class);
intent.putExtra(MAKAN, mList.get(pos));
startActivity(intent);
}}
So, my question is how to run the doFilter function with query by user input ? Is that possible ? thanks in advance
Image link
[1]: https://ibb.co/fFO3gQ - doFilter not work
[2]: https://ibb.co/dYXw1Q - static doFilter work
Assuming that you have added searchable.xml into res/xml/ project directory and in your AndroidManifest.xml, you have declared the MainActivity as searchable activity.
1. Add menu.xml into res/menu folder containing menu item that uses SearchView using app:actionViewClass="android.support.v7.widget.SearchView"
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_action_search"
android:title="#string/search_hint"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView" />
2. Setup SearchView and add SearchView.setOnQueryTextListener to your MainActivity.
3. Ony add a static Filter function into your Fragment class. For example:
public static void doFilter(String searchQuery) {
...........
....................
}
Update your MainActivity as below:
public class MainActivity extends AppCompatActivity {
Context mContext;
// Default active navigation menu
int mActiveMenu;
// TAGS
public static final int MENU_FIRST = 0;
public static final int MENU_SECOND = 1;
// Action bar search widget
SearchView searchView;
String searchQuery = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
................
...........................
// FirstFragment will show when app launch
mActiveMenu = MENU_FIRST;
displayViewWithFragment(mActiveMenu);
// NavigationView
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId())
{
case R.id.navigation_item_first:
{
// First
displayViewWithFragment(MENU_FIRST);
return true;
}
case R.id.navigation_item_second:
{
// Second
displayViewWithFragment(MENU_SECOND);
return true;
}
default:
return true;
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
// Getting search action from action bar and setting up search view
MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView)searchItem.getActionView();
// Setup searchView
setupSearchView(searchItem);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar actions click
switch (item.getItemId())
{
case R.id.action_search:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// Search widget
private void setupSearchView(MenuItem searchItem)
{
SearchManager searchManager = (SearchManager) this.getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null)
{
SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(info);
}
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText)
{
searchQuery = newText;
// Load search data on respective fragment
if(mActiveMenu == MENU_FIRST) // First
{
FirstFragment.doFilter(newText);
}
else if(mActiveMenu == MENU_SECOND) // Second
{
SecondFragment.doFilter(newText);
}
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
//searchView.clearFocus();
return false;
}
});
// Handling focus change of search view
searchView.setOnQueryTextFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
// Focus changed after pressing back key or pressing done in keyboard
if (!hasFocus) {
searchQuery = "";
}
}
});
}
/**
* Displaying fragment view for selected nav drawer list item
* */
private void displayViewWithFragment(final int position) {
// Active menu
mActiveMenu = position;
Fragment fragment = null;
switch (position)
{
case MENU_FIRST:
{
// First
fragment = new FirstFragment();
}
break;
case MENU_SECOND:
{
// Second
fragment = new SecondFragment();
}
break;
default:
break;
}
if (fragment != null)
{
mFragmentTransition = getSupportFragmentManager().beginTransaction();
mFragmentTransition.replace(R.id.frame_container, fragment);
mFragmentTransition.commit();
}
}
}
Add filter function to FirstFragment:
public static void doFilter(String searchQuery)
{
// Filter codes here
...................
.............................
// Update RecyclerView
adapter.notifyDataSetChanged();
}
Hope this will help~

FirebaseRecyclerAdapter will not inflate

Hello hoping someone can see what the problem is. Trying to grab data from firebase database and show it in a using FirebaseRecyclerAdapter but it only shows the data after I click on the searchview in the actionbar. Just can't figure out why.
public class CustomerFragment extends Fragment{
private FirebaseRecyclerAdapter<Customer,CustomerViewHolder> customerAdapter;
final String TAG = "CustomerFrag: ";
private EventBus eventBus = EventBus.getDefault();
private DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
private DatabaseReference customerRef = rootRef.child("customers");
private RecyclerView rvCustomer;
public CustomerFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
((AppStart)getActivity()).getSupportActionBar().setSubtitle("Customer List");
setHasOptionsMenu(true);
Log.d(TAG," onCreate");
}
// Inflate the menu; this adds items to the action bar if it is present.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu,inflater);
menu.clear();
inflater.inflate(R.menu.toolbar_customermenu, menu);
MenuItem searchItem = menu.findItem(R.id.customerSearch);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setQueryHint("Search Customer");
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
Log.d(TAG," onCreateOptionsMenu");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_customer, container, false);
rvCustomer = (RecyclerView)rootView.findViewById(R.id.rvCustomer);
rvCustomer.setHasFixedSize(true);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
rvCustomer.setLayoutManager(manager);
Log.d(TAG," onCreateView");
customerAdapter = new FirebaseRecyclerAdapter<Customer,CustomerViewHolder>(Customer.class, R.layout.customer_cardview, CustomerViewHolder.class, customerRef) {
#Override
protected void populateViewHolder(CustomerViewHolder viewHolder, final Customer customer, final int position) {
Log.d(TAG," populateViewHolder");
viewHolder.tvCustomerName.setText(customer.getCustomerName());
viewHolder.tvCustomerAddress.setText(customer.getCustomerAddress());
viewHolder.tvCustomerTel.setText(customer.getCustomerTel());
}
};
rvCustomer.setAdapter(customerAdapter);
return rootView;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
AppCompatActivity activity = (AppCompatActivity) getContext();
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
Log.d(TAG," onOptionsItemsSelected");
switch (item.getItemId()) {
case R.id.customerSearch:
Log.d(TAG,"Search icon pressed");
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
static class CustomerViewHolder extends RecyclerView.ViewHolder{
private TextView tvCustomerName;
private TextView tvCustomerAddress;
private TextView tvCustomerTel;
private CardView cvCustomer;
public CustomerViewHolder(View itemView) {
super(itemView);
tvCustomerName = (TextView)itemView.findViewById(R.id.tvCustomerName);
tvCustomerAddress = (TextView)itemView.findViewById(R.id.tvCustomerAddress);
tvCustomerTel = (TextView)itemView.findViewById(R.id.tvCustomerTel);
cvCustomer = (CardView)itemView.findViewById(R.id.cvCustomer);
Log.d("CustFragment"," CustomerViewHolder");
}
}
}
after days of hitting my head I figured it was the recyclerView layout height was not set to match_parent both the height and the width have to be match_parent.
Hope this helps someone.

I can't save instance of fragment to not restart after screen rotation

My fragment's code looks like this:
public class AllIssuesFragment extends Fragment {
#Bind(R.id.list_all_issues) ListView mListAllIssues;
IssuesGetter ai;
ArrayAdapter<IssuesResponse.Issue> adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_all_issues, container, false);
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
setRetainInstance(true);
SharedPreferences user_data = this.getActivity().getSharedPreferences("user_data", Context.MODE_PRIVATE);
UserManager.getInstance().setUsername(user_data.getString("username", null));
UserManager.getInstance().setPassword(user_data.getString("password", null));
if(UserManager.getInstance().getUsername() == null || UserManager.getInstance().getPassword() == null) {
Intent intent = new Intent(getActivity(), ChangeUserActivity.class);
startActivity(intent);
}
else {
adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1);
if(savedInstanceState == null) {
getIssues(Constants.URI + Constants.ISSUES + Constants.OFFSET + 0);
}
mListAllIssues.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
#Override
public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) {
boolean loadMore = firstVisible + visibleCount >= totalCount;
if (loadMore && ai.getStatus() == AsyncTask.Status.FINISHED) {
getIssues(Constants.URI + Constants.ISSUES + Constants.OFFSET + totalCount);
mListAllIssues.setSelection(totalCount);
}
}
});
}
}
private void getIssues(String url) {
ai = new IssuesGetter(new AsyncCallback<IssuesResponse>() {
#Override
public void onSuccess(IssuesResponse response) {
int index = mListAllIssues.getFirstVisiblePosition();
View v = mListAllIssues.getChildAt(0);
int top = (v == null)? 0 : v.getTop();
adapter.addAll(response.getIssues());
adapter.notifyDataSetChanged();
mListAllIssues.setAdapter(adapter);
mListAllIssues.setSelectionFromTop(index, top);
}
#Override
public void onError() {
Intent intent = new Intent(getActivity(), ChangeUserActivity.class);
startActivity(intent);
}
});
ai.execute(url);
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
#Bind(R.id.viewpager) ViewPager viewPager;
#Bind(R.id.tabs) PagerSlidingTabStrip tabStrip;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
viewPager.setAdapter(new MainActivityPagerAdapter(getSupportFragmentManager()));
tabStrip.setViewPager(viewPager);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_change_user) {
Intent intent = new Intent(this, ChangeUserActivity.class);
this.startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
}
I've tried to use setRetainInstance(true) and check if the savedInstanceState equals null, but it didn't solve my problem. I am stuck :(
My Asynctask returns result using call back.
I see the problem here:
public void onCreate() {
//..
viewPager.setAdapter(new MainActivityPagerAdapter(getSupportFragmentManager()));
tabStrip.setViewPager(viewPager);
}
This method is called each time activity is recreated. And what it does is creates new adapter which creates brand new fragments. And that is a problem. Because your activity doesn't control creation of fragments. That is neccessary in order to retain fragments.
I suggest you to save state of fragment in onSaveInstanceState() callback and restore it in onCreateView(). Note that you don't need to save state of UI elements just variables of fragment class. UI elements save their state automatically if they have unique id.
EDIT:
My suggestion:
public class AllIssuesFragment extends Fragment {
private List<String> issues;
// ..
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ..
if (null != savedInstanceState) {
issues = savedInstanceState.getStringArray("issues");
} else {
issues = new List<>();
}
adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, issues);
// ..
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putStringArray("issues", issues);
}
private void getIssues(String url) {
// ..
ai = new IssuesGetter(new AsyncCallback<IssuesResponse>() {
#Override
public void onSuccess(IssuesResponse response) {
// ..
//adapter.addAll(response.getIssues());
issues.addAll(response.getIssues());
adapter.notifyDataSetChanged();
// ..
}
};
// ..
}
}

Android don't load fragment (with Activity). Why?

I'm trying to go to a specific fragment and I intialisate this in Activity. But I don't get any error on my screen but on my device, my app is stopped running, he doesn't go in Fragment. What can be the problem? Thanx for you help. Below you find my code:
public class SubCatActivity extends Activity {
int hoofdCat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_subcat);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(R.id.container, new SubCatFragment())
.commit();
}
hoofdCat = Integer.parseInt(getIntent().getStringExtra("hoofdCat"));
}
public int getHoofdCat(){return hoofdCat;}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.info, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
My Fragment:
public class SubCatFragment extends Fragment implements SubCatFragmentInteractionListener {
private SubCatFragmentInteractionListener mListener;
public SubCatFragment(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_subcat, container, false);
ListView lstSubcat = (ListView) rootView.findViewById(R.id.lvSubcat);
ArrayList<String> subcat = new ArrayList<String>();
SubCatActivity activity = (SubCatActivity)getActivity();
int hoofdcat =activity.getHoofdCat();
DBAdapter db = new DBAdapter(getActivity().getBaseContext());
db.open();
Cursor c = db.getAllSubcat(hoofdcat);
if(c.moveToFirst())
{
do{
subcat.add(c.getString(1));
}while (c.moveToNext());
}
db.close();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, subcat);
lstSubcat.setAdapter(adapter);
lstSubcat.setOnItemClickListener(lstSubcatItemClickListener);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (SubCatFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement HoofdCatFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
private ListView.OnItemClickListener lstSubcatItemClickListener = new ListView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
//mListener.showSubCatActivity(pos+1);
}
};
}
Use FragmentActivity.
public class SubCatActivity extends FragmentActivity{
....
}
FragmentActivity
Replace or add the fragment inside onPostCreate, not on onCreate.

Categories

Resources