I have Fragment which have a searchview and viewpager . My viewpager has 3 fragments and each fragment calling adapter . Now to implement searchview , i need to call adapter of visible fragment in view pager .
SlidingTab(Fragment with searchview and ViewPager):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frame_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.RareMediaCompany.BDTrial.SlidingTab">
<include
android:id="#+id/toolbar1"
layout="#layout/toolbar_job" />
<com.RareMediaCompany.BDTrial.Utils.CustomTabLayout
android:id="#+id/sliding_tabs"
style="#style/CustomTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#eeeeee"
app:tabIndicatorColor="#f39220"
app:tabIndicatorHeight="3dp"
app:tabMaxWidth="0dp"
app:tabMode="fixed"
app:tabPaddingEnd="0dp"
app:tabPaddingStart="0dp"
app:tabTextAppearance="#android:style/TextAppearance.Widget.TabWidget"
app:tabSelectedTextColor="#808080" />
<LinearLayout
android:id="#+id/linear1"
android:background="#android:color/white"
android:layout_width="match_parent"
android:layout_height="70dp"
android:orientation="horizontal"
android:weightSum="1">
<android.support.v7.widget.SearchView
android:layout_width="300dp"
android:layout_height="45dp"
android:id="#+id/searchView"
android:layout_weight="0.9"
android:layout_marginRight="5dp"
android:layout_gravity="center"
style="#style/CitySearchView"
android:background="#drawable/searchview"
android:layout_marginLeft="10dp"/>
<LinearLayout
android:id="#+id/list_linearlayout"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_weight="0"
android:layout_gravity="center"
android:background="#f39220">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_weight="0.3"
android:src="#drawable/list_icon_white"/>
</LinearLayout>
<LinearLayout
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="center"
android:layout_weight="0"
android:layout_marginRight="10dp"
android:background="#75aadb">
<ImageView
android:layout_width="20dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginRight="2dp"
android:layout_weight="0.3"
android:src="#drawable/mapmarker"/>
</LinearLayout>
</LinearLayout>
<!--android:layout_width="320dp"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_marginLeft="10dp"-->
<!--android:layout_marginTop="10dp"-->
<!--android:id="#+id/searchview"/>-->
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/white" />
</LinearLayout>
SlidingTab.class (Implementing SearchView)
public class SlidingTab extends Fragment {
private static final String TAG = "TabLayout";
private static String POSITION = "POSITION";
private Context context;
private SearchView searchview;
private Toolbar toolbar ;
/*searching/filteration query*/
private SearchView.OnQueryTextListener OnQuerySearchView = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String arg0) {
// TODO Auto-generated method stub
// if (searchCheck) {
Log.i("Recycler query", arg0);
// Fragment frag = new PageAdapter(getChildFragmentManager(),context).getItem(viewPager.getCurrentItem());
PageAdapter adapter = ((PageAdapter) viewPager.getAdapter());
Fragment fragment = adapter.getFragment(viewPager.getCurrentItem());
return false;
}
};
public SlidingTab() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.sliding_tab, container, false);
viewPager = (ViewPager) v.findViewById(R.id.view_pager);
viewPager.setOffscreenPageLimit(2);
viewPager.setAdapter(new PageAdapter(getChildFragmentManager(), context));
slidingTab = (TabLayout) v.findViewById(R.id.sliding_tabs);
searchview = (SearchView)v.findViewById(R.id.searchView);
searchview.setOnQueryTextListener(OnQuerySearchView);
return v;
}
PageAdapter.class
public class PageAdapter extends FragmentStatePagerAdapter {
private static final String TAG = "PageAdapter";
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[]{"New", "In Progress", "Completed"};
private Context context;
public PageAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public Fragment getItem(int position) {
Log.d(TAG, "New Instance Created :" + position);
switch (position) {
case 0:
return new JobFragment();
case 1:
return new InProgressJobFragment();
case 2:
return new CompletedJobFragment();
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
#Override
public int getCount() {
return PAGE_COUNT;
}
}
Fragment RecyclerView Adapter (Call by each fragment in view pager and have searchview filter method)
public class JobAdapter extends RecyclerView.Adapter<JobAdapter.ViewHolder> {
private static final String TAG = "EMPLOYEE ADAPTER";
private static final int VIEW_NORMAL = 0;
private ArrayList<Info> mDataset;
private ArrayList<Info> filterList;
private Context mAct;
public class ViewHolder extends RecyclerView.ViewHolder {
}
}
public void addApplications(ArrayList<Info> candidates) {
}
public void clearApplications() {
}
public JobAdapter(ArrayList<Info> myDataset, Context context) {
this.mDataset = myDataset;
this.mAct = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.job_card_new, parent, false);
ViewHolder fh = new ViewHolder(v);
return fh;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// }
**// *searching/filtration on List*/**
public void filter(String charText) {
filterList.clear();
if (charText.length() == 0) {
if(mDataset != null) {
filterList.addAll(mDataset);
}
} else {
if (mDataset != null){
for (Info wp : mDataset) {
if(wp.jobNumber !=null){
if(Pattern.compile(Pattern.quote(charText), Pattern.CASE_INSENSITIVE).matcher(wp.jobNumber).find()){
// if (wp.heading1.toLowerCase().contains(charText.toLowerCase())) {
filterList.add(wp);
}}else{
}
this.notifyItemRangeRemoved(0, filterList.size());
}
}
}
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
Please help me in implementing searchview in viewpager .
With help of uploaded code
I can tell that
make method in your fragments named search and
call adapter filter method
public void search(String text)
{
adapter.filter(text)
}
you can check instance of fragment and call search method of fragment after this line
Fragment fragment = adapter.getFragment(viewPager.getCurrentItem());
I think the best design for this is to use the Activity as the central "hub" for events that need to go the fragments.
So this is how I would do this:
First start with a listener interface. This can be declared as an inner interface of the Activity:
static interface QueryListener {
void onQueryChange(String query);
}
Activity gets properties for holding listeners and methods for adding and removing listeners (declared synchronized to prevent those pesky ConcurrentModificationExceptions:
private List<QueryListener> mQueryListeners = new ArrayList<>();
public synchronized void addQueryListener(#NonNull QueryListener listener) {
// check if the listener was already added
// you could also use a Set instead of a List for this
if (mQueryListeners.contains(listener)) return;
mQueryListeners.add(listener);
}
public synchronized void removeQueryListener(#NonNull QueryListener listener) {
mQueryListeners.remove(listener);
}
Activity also gets a method that can be called by the fragment with the SearchView:
public synchronized void changeQuery(String query) {
for (QueryListener listener : mQueryListeners) {
listener.onQueryChange(query);
}
}
Now your fragments with the adapters need to implement QueryListener and register/unregister themselves:
Add this line somewhere in onCreate():
((YourActivity) getActivity()).addQueryListener(this);
Unregister in onDestroy():
#Override
public void onDestroy() {
((YourActivity) getActivity()).removeQueryListener(this);
super.onDestroy();
}
add the QueryListener method implementation:
#Override
public void onQueryChange(String query) {
// if (isVisible()) { if desired
mAdapter.filter(query);
}
Note: You don't have to have the fragment implement QueryListener; you can use an anonymous class. But you'll have to hold the reference to it so you can call removeQueryListener() with it later.
Now just hook up the SearchView:
#Override
public boolean onQueryTextChange(String query) {
((YourActivity) getActivity()).changeQuery(query);
}
Another pattern I've used is to create a dedicated class for registering/notifying listeners. I create a single instance of this class and have a method on the Activity to access it:
QueryHandler handler = ((YourActivity) getActivity()).getQueryHandler();
// QueryHandler has all the listener properties and methods shown for the Activity
...
handler.changeQuery(query);
Alternatively, you can also use one of the many open-source event bus packages like Otto to pass events amongst your fragments.
Related
I have implemented the SwipeRefreshLayout in many of the pages,and it working fine. but here i got stuck with one specific implementation , where i have a SwipeRefreshLayout for the ViewPager and ViewPager holding the FragmentPagerAdapter.
In my case , I have a ViewPager with two tabs and each holding the fragment with RecyclerView. On main page I have a SwipeRefreshLayout and on the onRefresh i need to load the API and update the fragments in ViewPager. Updating is working fine but unfortunately RecyclerView inside the Fragment ( ViewPager tab Item ) not scrolling top and it always calling the SwipeToRefresh.
I am familiar with using the SwipeRefreshLayout with RecyclerView, but here the problem is the main child of the SwipeRefreshLayout is ViewPager and it having the Fragment inside it and that fragment is holding the RecyclerView.
I have a thought of moving the SwipeRefreshLayout inside the fragments for the RecyclerView , but again here i have challenges like both the Fragments is having the same API. So that i am using the SwipeRefreshLayout directly on ViewPager to refresh my data.
Here is some of my codes.
MainContacts.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/ll_no_records"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:id="#+id/iv_retry"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:contentDescription="#string/todo"
android:src="#drawable/ic_reload" />
<TextView
android:id="#+id/textError"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:gravity="center"
android:text="#string/no_contact_found"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#color/colorDarkGray" />
</LinearLayout>
<LinearLayout
android:id="#+id/ll_process"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:alpha="1"
android:gravity="center"
android:orientation="vertical"
android:visibility="visible">
<ProgressBar
android:id="#+id/progress"
android:layout_width="50dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:indeterminate="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/fetching"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#color/colorDarkGray" />
</LinearLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/contacts_screen"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<android.support.design.widget.TabLayout
android:id="#+id/my_contacts_tabs"
style="#style/MyCustomTabLayout"
android:layout_width="match_parent"
app:tabBackground="#color/colorWhite"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="#+id/my_contacts_view_pager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="#android:color/transparent" >
</android.support.v4.view.ViewPager>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
contacts.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:hc="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/ll_no_records"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:id="#+id/iv_retry"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:contentDescription="#string/todo"
android:src="#drawable/ic_reload" />
<TextView
android:id="#+id/textError"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:gravity="center"
android:text="#string/no_contact_found"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#color/colorDarkGray" />
</LinearLayout>
<com.diegocarloslima.fgelv.lib.FloatingGroupExpandableListView
android:id="#+id/contactList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/searchContainer"
android:animateLayoutChanges="true"
android:childDivider="#android:color/transparent" />
</RelativeLayout>
MainFragment ( Which i am using to load the child fragments , SwipeTORefreshLayout + ViewPager here)
public class MainFragment extends BaseFragment {
private TextView mTextError;
private LinearLayout llNoRecords, ll_process;
private ImageView iv_retry;
private MaterialSearchView materialSearchView;
PHCJsonResponseContactDetailModel mContactResponseModel;
int expandableListSelectionType = ExpandableListView.PACKED_POSITION_TYPE_NULL;
boolean actionModeEnabled;
private Activity mActivity;
SwipeRefreshLayout mSwipeRefreshLayout;
private ViewPager viewPager;
TabLayout tabLayout;
ContactsTabPagerAdapter mAdapter;
ArrayList<PHCContactDetailModel> mContactList =new ArrayList<>();
ArrayList<PHCContactDetailModel> mFavoriteList;
boolean isSwipeToRefresh;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mActivity = getActivity();
View view = inflater.inflate(R.layout.phc_contact_fragment, container, false);
getViewId(view);
setListener();
if (isNetworkAvailable()) {
if(((MainDrawerActivity)mActivity).getPHCContactFragmentData()==null)
getAllContactData();
else
updateWidgets();
} else {
showNoNetworkToast();
llNoRecords.setVisibility(View.VISIBLE);
mTextError.setText(getResources().getText(R.string.no_internet_retry));
}
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onResume() {
super.onResume();
}
/*#Override
public void onPrepareOptionsMenu(final Menu menu) {
getActivity().getMenuInflater().inflate(R.menu.menu_fragment_group, menu);
}*/
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_fragment_contacts, menu);
MenuItem item = menu.findItem(R.id.action_search);
materialSearchView.setMenuItem(item);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_create_group) {
Intent createGroupIntent = new Intent(getActivity(), PHCCreateGroupActivity.class);
createGroupIntent.putExtra("comeFrom", PHCAppConstant.GROUP_ADD);
getActivity().startActivity(createGroupIntent);
}
return super.onOptionsItemSelected(item);
}
private void setListener() {
iv_retry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isNetworkAvailable()) {
getAllContactData();
} else {
showNoNetworkToast();
}
}
});
}
private void getViewId(View view) {
mTextError = (TextView) view.findViewById(R.id.textError);
ll_process = (LinearLayout) view.findViewById(R.id.ll_process);
llNoRecords = (LinearLayout) view.findViewById(R.id.ll_no_records);
iv_retry = (ImageView) view.findViewById(R.id.iv_retry);
viewPager = (ViewPager) view.findViewById(R.id.my_contacts_view_pager);
tabLayout = (TabLayout) view.findViewById(R.id.my_contacts_tabs);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary,
android.R.color.holo_green_dark,
android.R.color.holo_orange_dark,
android.R.color.holo_blue_dark);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
if(mContactResponseModel!=null && mContactResponseModel.getData().size() >0)
{
isSwipeToRefresh = true;
getAllContactData();
}
}
});
materialSearchView = (MaterialSearchView) getActivity().findViewById(R.id.search_view);
}
private void getAllContactData() {
if (isNetworkAvailable()) {
// showProgress();
PHCApiInterface apiService = PHCApiClient.getClient(getActivity()).create(PHCApiInterface.class);
Call<PHCJsonResponseContactDetailModel> call = apiService.contactData(getApplicationData(getActivity()).getAuthToken(), getApplicationData(getActivity()).getUserID());
call.enqueue(new Callback<PHCJsonResponseContactDetailModel>() {
#Override
public void onResponse(Call<PHCJsonResponseContactDetailModel> call, Response<PHCJsonResponseContactDetailModel> response) {
Log.d(TAG, "getContacts URL " + response.raw().request().url());
Log.d(TAG, "getContacts Resp " + new Gson().toJson(response.body()));
mContactResponseModel = response.body();
((MainDrawerActivity)mActivity).setPHCContactFragmentData(mContactResponseModel);
if(mSwipeRefreshLayout.isRefreshing())
{
// cancel the Visual indication of a refresh
mSwipeRefreshLayout.setRefreshing(false);
}
if(isSwipeToRefresh)
{
isSwipeToRefresh=false;
updateWidgets();
}
else
updateWidgets();
}
#Override
public void onFailure(Call<PHCJsonResponseContactDetailModel> call, Throwable t) {
if(mSwipeRefreshLayout.isRefreshing())
{
// cancel the Visual indication of a refresh
mSwipeRefreshLayout.setRefreshing(false);
}
isSwipeToRefresh=false;
dismissProgress();
mTextError.setVisibility(View.VISIBLE);
}
});
} else {
isSwipeToRefresh=false;
if(mSwipeRefreshLayout.isRefreshing())
{
// cancel the Visual indication of a refresh
mSwipeRefreshLayout.setRefreshing(false);
}
showNoNetworkAlert();
}
}
private void updateWidgets() {
if (mContactResponseModel.getStatusCode() == 401 || mContactResponseModel.getStatusCode() == 402) {
showSessionExpireAlert(mContactResponseModel.getStatusMessage(), mContactResponseModel.getStatusCode());
return;
}
if (mContactResponseModel != null && mContactResponseModel.getStatusCode() == 1) {
dismissProgress();
mTextError.setVisibility(View.GONE);
mContactList = mContactResponseModel.getData();
mFavoriteList = mContactResponseModel.getData();
if(mContactList!=null && mContactList.size()>0)
{
llNoRecords.setVisibility(View.GONE);
mAdapter = new ContactsTabPagerAdapter(getActivity().getApplicationContext(), getChildFragmentManager(), mContactList , mFavoriteList);
viewPager.setAdapter(mAdapter);
tabLayout.setupWithViewPager(viewPager);
}
else {
llNoRecords.setVisibility(View.VISIBLE);
}
} else {
dismissProgress();
mTextError.setVisibility(View.VISIBLE);
}
}
public void dismissProgress() {
ll_process.setVisibility(View.GONE);
super.dismissProgress();
}
private void initiateContactChat(final PHCFacilityDetailsModel facilityDetailsModel, final int groupPosition, final int childPosition) {
String header = getApplicationData(getActivity()).getAuthToken();
PHCApiInterface apiService = PHCApiClient.getClient(getActivity()).create(PHCApiInterface.class);
Call<PHCContactInitiateChatResponseModel> call = apiService.initiateContactChat(header, facilityDetailsModel.getUserId(), getApplicationData(getActivity()).getUserID(), 0);
call.enqueue(new Callback<PHCContactInitiateChatResponseModel>() {
#Override
public void onResponse(Call<PHCContactInitiateChatResponseModel> call, Response<PHCContactInitiateChatResponseModel> response) {
Log.d(TAG, "initiateContactChat URL " + response.raw().request().url());
Log.d(TAG, "initiateContactChat Resp " + new Gson().toJson(response.body()));
PHCContactInitiateChatResponseModel mContactInitiateChatModel = response.body();
if (mContactInitiateChatModel != null && mContactInitiateChatModel.getStatusCode() == 1) {
Intent chatIntent = new Intent(getActivity(), PHCChatActivity.class);
// chatIntent.putExtra("headerName",mData.get(groupPosition).getFacilityDetails().get(childPosition).getUserName());
chatIntent.putExtra("headerName", facilityDetailsModel.getUserName());
chatIntent.putExtra("groupId", mContactInitiateChatModel.getData().getGroupId());
getActivity().startActivity(chatIntent);
}
}
#Override
public void onFailure(Call<PHCContactInitiateChatResponseModel> call, Throwable t) {
Toast.makeText(getActivity(), "Something went wrong! Please try again", Toast.LENGTH_SHORT).show();
}
});
}
}
ContactsTabPagerAdapter.java
public class ContactsTabPagerAdapter extends FragmentPagerAdapter {
/**
* The Page count.
*/
final int PAGE_COUNT = 2;
private String[] tabTitles = { "Contacts", "Favorites" };
private ArrayList<PHCContactDetailModel> mContactsList;
private ArrayList<PHCContactDetailModel> mFavoritesList;
Context mContext ;
public ContactsTabPagerAdapter(Context context, FragmentManager fm ,ArrayList<PHCContactDetailModel> contacts , ArrayList<PHCContactDetailModel> favs) {
super(fm);
this.mContext = context;
this.mContactsList = contacts;
this.mFavoritesList=favs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
ContactsFragment mContactsFragment =new ContactsFragment();
Bundle bundle=new Bundle();
bundle.putSerializable("Contacts", (Serializable) mContactsList);
mContactsFragment.setArguments(bundle);
return mContactsFragment;
case 1:
FavoritesFragment mFavoritesFragment=new FavoritesFragment();
Bundle pastBundle=new Bundle();
pastBundle.putSerializable("Favorites", (Serializable) mFavoritesList);
mFavoritesFragment.setArguments(pastBundle);
return mFavoritesFragment;
}
return null;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
/**
* Update.
*
* #param lContactsList contact list to update
* #param lFavoritesList favorites list to update
*/
//call this method to update fragments in ViewPager dynamically
public void update(ArrayList<PHCContactDetailModel> lContactsList, ArrayList<PHCContactDetailModel> lFavoritesList) {
this.mContactsList = lContactsList;
this.mFavoritesList = lFavoritesList;
notifyDataSetChanged();
}
#Override
public int getItemPosition(Object object) {
if (object instanceof UpdatableFragment) {
((UpdatableFragment) object).update(mContactsList, mFavoritesList);
}
//don't return POSITION_NONE, avoid fragment recreation.
return super.getItemPosition(object);
}
}
ContactsFragment.java
public class ContactsFragment extends BaseFragment implements UpdatableFragment{
private static final String TAG = "ContactFragmentTab";
private FloatingGroupExpandableListView mContactExpandableList;
private PHCContactAdapter mAdapter;
WrapperExpandableListAdapter wrapperAdapter;
boolean actionModeEnabled;
private LinearLayout llNoRecords;
private ArrayList<PHCContactDetailModel> mContactsData;
public ContactsFragment() {
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
}
#SuppressWarnings("unchecked")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_contacts, container, false);
getViewId(rootView);
Bundle bundle= getArguments();
if(bundle !=null)
{
Log.d(TAG, "bundle is not empty");
mContactsData= (ArrayList<PHCContactDetailModel>) bundle.getSerializable("Contacts");
}
System.out.print("Contacts Size::" + mContactsData.size());
if(mContactsData!=null)
{
updateWidgets();
}
return rootView;
}
private void updateWidgets() {
mAdapter = new PHCContactAdapter(getActivity(), mContactsData, new ListShowingHidingListener() {
#Override
public void listHideAndShow(boolean isData) {
if (isData) {
llNoRecords.setVisibility(View.GONE);
mContactExpandableList.setVisibility(View.VISIBLE);
listUpdate();
} else {
llNoRecords.setVisibility(View.VISIBLE);
mContactExpandableList.setVisibility(View.GONE);
}
}
});
wrapperAdapter = new WrapperExpandableListAdapter(mAdapter);
mContactExpandableList.setAdapter(wrapperAdapter);
try {
for (int i = 0; i < wrapperAdapter.getGroupCount(); i++) {
mContactExpandableList.expandGroup(i);
}
} catch (Exception e) {
Log.e("Exception in Expand", "" + e);
}
}
private void listUpdate() {
try {
for (int i = 0; i < wrapperAdapter.getGroupCount(); i++) {
mContactExpandableList.expandGroup(i);
}
} catch (Exception e) {
Log.e("Exception in Expand", "" + e);
}
}
private void getViewId(View view) {
// mContactExpandableList = (ExpandableListView) view.findViewById(R.id.contactList);
mContactExpandableList = (FloatingGroupExpandableListView) view.findViewById(R.id.contactList);
}
#Override
public void update(ArrayList<PHCContactDetailModel> contactsData, ArrayList<PHCContactDetailModel> favoritesData) {
this.mContactsData = contactsData;
updateWidgets();
}
}
similarly i have Favorites example as well. Mostly both will look like same, that's why not posting it here.
Sorry for posting the long question. Any help regarding this. Apologies for my poor English. Thanks in Advance.
I want to set the visibility of my relativelayout from my fragment using my adapter see the image below
HERE IS MY FRAGMENT
I declare relativeLayout to public so i can access it on my adapter to set its visibility but i always get an null error
How i can set the relativelayout visibility to visible when i click my checkbox. Please help me. Thanks a lot.
public class FoodListFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
public RelativeLayout relativeLayout;
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private Food_RecyclerAdapter adapter;
private List<Food> foods;
private ApiInterface apiInterface;
ProgressBar progressBar;
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public FoodListFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment FoodListFragment.
*/
// TODO: Rename and change types and number of parameters
public static FoodListFragment newInstance(String param1, String param2) {
FoodListFragment fragment = new FoodListFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_food_list, container, false);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
recyclerView = (RecyclerView)view.findViewById(R.id.recycleViewFood);
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
relativeLayout = (RelativeLayout)view.findViewById(R.id.cart_add);
relativeLayout.setVisibility(View.GONE);
apiInterface = ApiClient.getClient().create(ApiInterface.class);
progressBar = (ProgressBar)view.findViewById(R.id.progress_bar);
progressBar.setVisibility(View.VISIBLE);
Bundle bundle = this.getArguments();
String category_id = bundle.getString("menu_id");
Call<List<Food>> call = apiInterface.getFoodList(category_id);
call.enqueue(new Callback<List<Food>>() {
#Override
public void onResponse(Call<List<Food>> call, Response<List<Food>> response) {
foods = response.body();
adapter = new Food_RecyclerAdapter(getContext(),foods);
recyclerView.setAdapter(adapter);
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<List<Food>> call, Throwable t) {
progressBar.setVisibility(View.GONE);
Toast.makeText(getContext(), "Please check your network connection", Toast.LENGTH_SHORT).show();
}
});
EditText searhText = (EditText)view.findViewById(R.id.search_food);
searhText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getfilter().filter(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
HERE IS MY ADAPTER
public class Food_RecyclerAdapter extends RecyclerView.Adapter<Food_RecyclerAdapter.myViewHolder>{
Context context;
public List<Food> foods;
public List<Food> mOriginalValues;
public List<Food> mDisplayedValues;
ApiClient apiClient;
FoodListFragment foodListFragment;
public Food_RecyclerAdapter(Context context,List<Food> foods){
this.context = context;
this.foods = foods;
this.mOriginalValues = foods;
this.mDisplayedValues = foods;
}
#Override
public myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_list_row,parent,false);
return new myViewHolder(view);
}
#Override
public void onBindViewHolder(final myViewHolder holder, int position) {
apiClient = new ApiClient();
Picasso.with(context).load(apiClient.BASE_URL + foods.get(position).getImage()).into(holder.food_image);
holder.food_check.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(holder.food_check.isChecked()){
//HERE I WANT TO SHOW THE RELATIVE LAYOUT WHEN I CLICK MY CHECKBOX
foodlistFragment = new FoodListFragment();
foodListFragment.relativeLayout.setVisibility(View.VISIBLE);
}else{
holder.food_qty.setText(""+0);
}
}
});
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getItemCount() {
return foods.size();
}
public class myViewHolder extends RecyclerView.ViewHolder{
TextView food_price,food_availability,food_qty;
ImageView food_image,remove_image,add_image;
CheckBox food_check;
public myViewHolder(View itemView) {
super(itemView);
food_check = (CheckBox) itemView.findViewById(R.id.radioFood_name);
food_image = (ImageView)itemView.findViewById(R.id.food_image);
food_availability = (TextView) itemView.findViewById(R.id.food_availability);
food_price = (TextView) itemView.findViewById(R.id.food_price);
food_qty = (TextView) itemView.findViewById(R.id.food_qty);
add_image = (ImageView)itemView.findViewById(R.id.add_image);
remove_image = (ImageView)itemView.findViewById(R.id.remove_image);
}
}
}
Here is the XML
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.jampol.blogs.FoodListFragment">
<EditText
android:layout_width="match_parent"
android:layout_height="40dp"
android:id="#+id/search_food"
android:drawableStart="#drawable/ic_search"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:drawablePadding="10dp"
android:hint="Search.."
android:gravity="center_vertical"
android:textSize="18dp"
android:background="#color/colorPrimary"
android:textColorHint="#color/white"
android:textColor="#color/white"
/>
<ProgressBar
android:id="#+id/progress_bar"
style="?android:progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_centerInParent="true"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycleViewFood"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:layout_below="#+id/search_food"
android:layout_alignParentStart="true"
android:layout_above="#+id/cart_add">
</android.support.v7.widget.RecyclerView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/cart_add"
android:layout_alignParentBottom="true"
android:padding="5dp"
android:layout_alignParentStart="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total"
android:textSize="16dp"
android:paddingRight="10dp"
android:layout_centerVertical="true"
android:textStyle="bold"
android:id="#+id/total"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/total"
android:text="100000"
android:textSize="16dp"
android:layout_centerVertical="true"
android:textStyle="bold"
/>
<Button
android:layout_width="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#color/red"
android:textColor="#color/white"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:text="Add to cart" />
</RelativeLayout>
Hope this will help you.
You do not need to pass fragment's object in your adapter nor you need to define Relativelayout in your fragment as a public.
Follow this steps it may be lengthy but you can achieve your desire result :
Just pass your activity of fragment as a context in your adapter.
Like this :
adapter = new Food_RecyclerAdapter(getActivity(),foods);
Then in your adapter where you want to show or hide your views do something
like this:
Cast your context to your fragment's activity. Let's your fragment is inside
your MainActivity. So this would be :
MainActivity mActivity = ((MainActivity)context);
Make a public method in your MainActivity and getCurrentFragment of your
activity something like this:
public void showHideViews(){
Fragment currentFragment = getActiveFragment();
if(currentFragment != null){
//Access public method of your fragment from here
((FoodListFragment)currentFragment).showHideViews();
}
}
Make showHideViews() method in your FoodListFragment :
public void showHideViews(){
yourRelativeLayout.setVisibility(View.GONE);
}
First time it looks lengthy but this will be convenient.
Hope it helps you.
you need to pass a listener to your fragment like this:
in your adapter:
private MyClickListener clickListener;
interface MyClickListener{
void onClick(View v, int position);
}
public void setOnMyClickListener(MyClickListener clickListener){
this.clickListener = clickListener;
}
in your holder.food_check onClick:
if(clickListener != null){
clickListener.onClick(v,position);
}
in your fragment(when create adapter):
adapter.setOnMyClickListener(new Food_RecyclerAdapter.MyClickListener()
{
#Override
public void onClick(View v,int position) {
relativeLayout.setVisibility(View.VISIBLE);//or gone
}
});
Your foodListFragment object is not initialized in adapter class. it is null and you are trying to call foodListFragment.relativeLayout.setVisibility(View.VISIBLE); on checkbox click listener in adapter.
So pass foodListFragment reference from Fragment to Adapter class and in adapter class constructor make sure it is initialized.
Objective: I have one activity and within two fragments. The ideia is to communicate both fragments, selecting one category and updating its item list.On activity load, a category is settle by default.
Problem: On activity load, ItemsFragment doesn't display/update itemsLisView. Also ItemAdapter's getView Method is being called only twice, even though the list has five items.
Facts:
Items List is being correctly fulfilled before being passed to adapter
Breakpointing the code, not sure why or if it matters, ItemsFragment is being rendered/called before CategoriesFragments. I found this weird since CategoriesFragments is positioned above ItemsFragment. This is the reason why I wrote if (getArguments() != null). Before I was getting Null Pointer Exception.
Research: There is a lot of questions regarding both subjects.
Android ListView not refreshing after notifyDataSetChanged with data as Map
ListFragment Not Rendering and getView() in Adapter Not Being Called
Android getView() not being called properly?
BaseAdapter notifyDatasetChanged() called but getView() is never called
Those are some link examples (of thousands) I went through, trying to find a solution for my case. Unfortunately none of them worked.
I've been with this problem for almost 5 days now and I guess I missing some Android concept here. It's not something related with Java Programming, or at least I hope so.
Questions:
Why ItemsFragment is not displaying Items List on activity load? (This probably answers updating problem)
Why ItemAdapter just calls getView only twice, even that Items List is correctly given to him with more items?
For any further needed information, please don't mind to ask.
Thanks in advance for any help.
EDIT - MCVE:
activity_triple_list:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".controller.activities.Lists">
<include layout="#layout/content_triple_list" />
</android.support.design.widget.CoordinatorLayout>
content_triple_list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/listsPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="4dp"
android:paddingTop="4dp" />
</android.support.v4.view.ViewPager>
</LinearLayout>
fragment_categories:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/categoriesFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TableLayout
android:id="#+id/categoriesTable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:stretchColumns="4">
<TableRow
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:gravity="center_horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_marginLeft="13dp"
android:layout_marginRight="13dp"
android:orientation="vertical">
<TextView
android:id="#+id/category1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="CATEGORY 1"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</TableRow>
</TableLayout>
</LinearLayout>
fragment_items:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/itemsFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#+id/itemsListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="#null" />
</LinearLayout>
content_row_choose_item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/custom_row"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingLeft="15dp"
android:paddingTop="5dp">
<TextView
android:id="#+id/itemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TEST"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
custom_row:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:background="#2fff00">
<item android:drawable="#color/colorPrimary" android:state_pressed="true" /> <!-- pressed -->
</selector>
ApplicationUtils:
public final class ApplicationUtils extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
ApplicationUtils.context = getApplicationContext();
}
public static Context getContext() {
return ApplicationUtils.context;
}
public static String getJavaPackageName() {
return ApplicationUtils.context.getPackageName();
}
public static Resources getAppResources() {
return getContext().getResources();
}
public static String getResouceName(Integer id) {
return getAppResources().getResourceName(id);
}
public static String getResourceString(Integer id) {
return getAppResources().getString(id);
}
public static int getResourceId(String variableName, String resourceName, String packageName) {
try {
return getContext().getResources().getIdentifier(variableName, resourceName, packageName);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
}
Lists:
public class Lists extends AppCompatActivity implements CategoriesFragment.OnHeadlineSelectedListener {
private String listName;
public void onItemSelected(String currentCategory) {
ItemsFragment itemsCallBackFragment = (ItemsFragment) getSupportFragmentManager().findFragmentById(R.id.itemsFragment);
if (itemsCallBackFragment != null) {
itemsCallBackFragment.updateArticleView(currentCategory);
} else {
ItemsFragment itemFragment = new ItemsFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.itemsFragment, itemFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_triple_list);
setListsAdapter();
}
private void setListsAdapter() {
ViewPager tripleListViewPager = (ViewPager) findViewById(R.id.listsPager);
FragmentPagerAdapter tripleListFragmentAdapt = new ListsPagerAdapter(getSupportFragmentManager(), "LIST NAME", ApplicationUtils.getContext());
tripleListViewPager.setAdapter(tripleListFragmentAdapt);
}
}
ListsPagerAdapter:
public class ListsPagerAdapter extends FragmentPagerAdapter {
private static int NUM_TABS = 1;
private String listName;
private Context listsContext;
public ListsPagerAdapter(FragmentManager fm, String newListName, Context listsContext) {
super(fm);
setListName(newListName);
setListsContext(listsContext);
}
// Returns total number of pages
#Override
public int getCount() {
return NUM_TABS;
}
// Returns the fragment to display for that page
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return NewItemPagerFragment.newInstance();
default:
return null;
}
}
// Returns the page title for the top indicator
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return listsContext.getResources().getString(R.string.lists_tab_newItem, getListName());
default:
return "$value";
}
}
public String getListName() {
return listName;
}
public void setListName(String listName) {
this.listName = listName;
}
public Context getListsContext() {
return listsContext;
}
public void setListsContext(Context listsContext) {
this.listsContext = listsContext;
}
}
CategoriesFragment:
public class CategoriesFragment extends Fragment {
private List<Integer> categoryIds = new ArrayList<>();
private String currentCategory;
private View categoriesView;
OnHeadlineSelectedListener itemCallback;
public interface OnHeadlineSelectedListener {
void onItemSelected(String categoryName);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
itemCallback = (OnHeadlineSelectedListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
categoriesView = inflater.inflate(R.layout.fragment_categories, container, false);
categoriesView.setId(R.id.categoriesFragment);
return categoriesView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setCategoriesListener();
setDefaultSelectedCategory();
}
private void setCategoriesListener() {
categoryIds.add(R.id.category1);
for (Integer id : categoryIds) {
setListener(id);
}
}
private void setListener(final int categoryId) {
final ImageView categoryImg = (ImageView) categoriesView.findViewById(categoryId);
categoryImg.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
removePreviousSelectedCategory(categoryImg);
selectCategory(categoryId, categoryImg);
loadItemList();
}
});
}
private void removePreviousSelectedCategory(ImageView categoryImg) {
for (Integer id : categoryIds) {
final ImageView imgView = (ImageView) categoriesView.findViewById(id);
if (imgView.getTag() != null) {
String previousSelectedCategory = (String) imgView.getTag();
if (StringUtils.contains(previousSelectedCategory, Application.SELECTED)) {
previousSelectedCategory = previousSelectedCategory.replace(Application.SELECTED, "");
categoryImg.setTag(previousSelectedCategory);
Integer previousSelectedCategoryId = ApplicationUtils.getResourceId(previousSelectedCategory, Application.RES_DRAWABLE, ApplicationUtils.getJavaPackageName());
imgView.setImageResource(previousSelectedCategoryId);
}
}
}
}
private void selectCategory(int categoryId, ImageView categoryImg) {
String newSelectedCategory = ApplicationUtils.getResouceName(categoryId) + Application.SELECTED;
setCurrentCategory(newSelectedCategory);
newSelectedCategory = newSelectedCategory.replace(Application.META_INFO_ID, "");
categoryImg.setTag(newSelectedCategory);
Integer currentCategoryId = ApplicationUtils.getResourceId(newSelectedCategory, Application.RES_DRAWABLE, ApplicationUtils.getJavaPackageName());
categoryImg.setImageResource(currentCategoryId);
}
public String getCurrentCategory() {
return currentCategory;
}
public void setCurrentCategory(String currentCategory) {
this.currentCategory = currentCategory;
}
private void loadItemList() {
itemCallback.onItemSelected(getCurrentCategory());
}
private void setDefaultSelectedCategory() {
Integer categoryId = R.id.category1;
final ImageView categoryImg = (ImageView) categoriesView.findViewById(categoryId);
selectCategory(categoryId, categoryImg);
loadItemList();
}
}
ItemsFragment:
public class ItemsFragment extends Fragment {
private View itemsFragmentView;
private ListView itemsListView;
private ItemAdapter itemsListAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
itemsFragmentView = inflater.inflate(R.layout.fragment_items, container, false);
itemsListView = (ListView) itemsFragmentView.findViewById(R.id.itemsListView);
setItemsListAdapter();
return itemsFragmentView;
}
public void updateArticleView(String categoryName) {
getSelectedCategoryList();
}
private void getSelectedCategoryList() {
List<String> testList = new ArrayList<>();
testList.add("TEST ITEM");
itemsListAdapter.update(testList);
}
private void setItemsListAdapter() {
itemsListAdapter = new ItemAdapter(getActivity(), R.layout.fragment_items, new ArrayList<String>());
itemsListView.setAdapter(itemsListAdapter);
}
}
ItemAdapter:
public class ItemAdapter extends ArrayAdapter<String> {
private List<String> items = new ArrayList<>();
private LayoutInflater rowInflater;
public ItemAdapter(Context context, int resource, List<String> itemsList) {
super(context, resource, itemsList);
this.items = itemsList;
this.rowInflater = LayoutInflater.from(context);
}
private class ItemHolder {
TextView itemNameView;
}
#Override
public View getView(int position, View rowView, ViewGroup parent) {
ItemHolder itemHolder;
if (rowView == null) {
rowView = rowInflater.inflate(R.layout.content_row_choose_item, parent, false);
itemHolder = new ItemHolder();
itemHolder.itemNameView = (TextView) rowView.findViewById(R.id.itemName);
rowView.setTag(itemHolder);
} else {
itemHolder = (ItemHolder) rowView.getTag();
}
String itemName = getItem(position);
if (StringUtils.isNotEmpty(itemName) && itemHolder.itemNameView != null) {
itemHolder.itemNameView.setText(itemName);
System.out.println("ITEM NAME ### " + itemHolder.itemNameView.getText());
}
return rowView;
}
public void update(List<String> items) {
this.items.clear();
this.items.addAll(items);
this.notifyDataSetChanged();
}
public List<String> getItems() {
return items;
}
}
Random stab...
If using a ListFragment, then fragment_items.xml needs a ListView with android:id="#android:id/list".
You are even trying to load the ListView with that id.
itemsFragmentView = inflater.inflate(R.layout.fragment_items, container, false);
itemsListView = (ListView) itemsFragmentView.findViewById(android.R.id.list);
However, you have android:id="#+id/itemsListView"
fragment_items:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/itemsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#+id/itemsListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:divider="#null" />
</LinearLayout>
If using a ListFragment, you do not need to implement your own XML layout file. That being said, onCreateView doesn't need implemented. Use onActivityCreated instead.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
itemsListView = getListView();
itemsListAdapter = new ItemAdapter(getActivity());
setListAdapter(itemsListAdapter);
super.onActivityCreated(savedInstanceState);
}
Now, if you want to add items to the adapter, I generally recommend you just use an ArrayAdapter<String>. This will provide you an add(String object) method that will both add to the underlying list and notify for updates.
Regarding the getView problems, can't really say. I don't really know why you need ItemAdapter since the default ArrayAdapter<String> will work assuming you pass it a layout with android:id="#android:id/text1, for example using android.R.layout.simple_list_item_1 in place of R.layout.content_row_choose_item
So, that would look something like.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
itemsListView = getListView();
ArrayAdapter<String> itemsListAdapter = new ArrayAdapter<String>(
getActivity(), android.R.layout.simple_list_item_1);
setListAdapter(itemsListAdapter);
adapter.add("Hello");
adapter.add("World");
super.onActivityCreated(savedInstanceState);
}
The given MCVE was working fine. After 7 days debugging and uncommenting code I found the answer to my problem.
My list was correctly being updated, but wasn't being rendered because of a second ItemsFragemnt being initialized on Lists Activity load. This second fragment was overlaying the first one and that's why I wasn't seing my list being displayed/refreshed.
Lists:
First created fragment:
private void setListsAdapter() {
ViewPager tripleListViewPager = (ViewPager) findViewById(R.id.listsPager);
FragmentPagerAdapter tripleListFragmentAdapt = new ListsPagerAdapter(getSupportFragmentManager(), "LIST NAME", ApplicationUtils.getContext());
tripleListViewPager.setAdapter(tripleListFragmentAdapt); }
Inside ListsPagerAdapter there was a call to populate my ViewPager (NewItemPagerFragment) with CategoriesFragment and ItemsFragment.
Second created fragment - Overlay:
ItemsFragment itemFragment = new ItemsFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.itemsFragment, itemFragment);
transaction.addToBackStack(null);
transaction.commit();
I tried to breakpoint my code, mentioned before in Facts at question scope, but sometimes this is really painful. I came with the idea to use Log.d(TAG_KEY, TAG_NAME); and that was when I found out the answer: I realized that ItemsFragment was being called twice on Activity load.
I searched for new ItemsFragment in my project and saw that inside my NewItemPagerFragment onCreate, ItemsFragment was being called. Also before CategoriesFragment- just like this:
NewItemPagerFragment:
Fragment itemsFragment = new ItemsFragment();
FragmentManager fm1 = getChildFragmentManager();
FragmentTransaction ft1 = fm1.beginTransaction();
ft1.replace(R.id.itemsFragment, itemsFragment);
ft1.commit();
Fragment categoriesFragment = new CategoriesFragment();
FragmentManager fm = getChildFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.categoriesFragment, categoriesFragment);
ft.commit();
which explains Facts 2.. After commenting/remove this call on NewItemPagerFragment the problem was gone.
Bottom line is: Make sure your list is correctly being fulfilled/updated with things like notifyDataSetChanged as cricket_007 mentioned in his answer and other thousand posts I read on internet. Not less, make sure you are not overlaying the fragment calling its initialization twice.
I´m using in my Android (4.0+) app fragment (in Activity) with Tab bar.
I want to create Espresso test but if I create main Activity and open the fragment. I get this Exception:
java.lang.IllegalStateException: ViewPager does not have adapter instance.
at com.astuetz.PagerSlidingTabStrip.setViewPager(PagerSlidingTabStrip.java:177)
at cz.villamemories.detoxme.staticcontent.StaticContentFragment.onCreateView(StaticContentFragment.java:197)
My code in fragment:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewPagerAdapter = new StaticContentPagerAdapter(
this.getChildFragmentManager(), mItemsList, categories);
mPager.setAdapter(mViewPagerAdapter);
mTabs.setViewPager(mPager); //line 197
Do you have some tip where can be a problem? What is wrong?
I was also facing the issue with ViewPager in fragment. This problem occurs me because of my viewpager has a multiple root elements.
#RunWith(JUnit4.class)
public class FragmentTest {
private static final String TAG = "FragmentTest";
#Rule
public ActivityTestRule<MainActivity> mActivity = new ActivityTestRule<MainActivity>(MainActivity.class);
#Test
public void checkTabSwiping() {
onView(nthChildOf(withId(R.id.main_content), 5)).check(matches(withId(R.id.homecontentgrouppager)));
}
public static Matcher<View> firstChildOf(final Matcher<View> parentMatcher) {
return new TypeSafeMatcher<View>() {
#Override
public void describeTo(Description description) {
description.appendText("with first child view of type parentMatcher");
}
#Override
public boolean matchesSafely(View view) {
if (!(view.getParent() instanceof ViewGroup)) {
return parentMatcher.matches(view.getParent());
}
ViewGroup group = (ViewGroup) view.getParent();
return parentMatcher.matches(view.getParent()) && group.getChildAt(0).equals(view);
}
};
}
public static Matcher<View> nthChildOf(final Matcher<View> parentMatcher,
final int childPosition){
return new TypeSafeMatcher<View>() {
#Override
public void describeTo(Description description) {
description.appendText("with " + childPosition + " child view of type parentMatcher");
}
#Override
public boolean matchesSafely(View view) {
if (!(view.getParent() instanceof ViewGroup)) {
return parentMatcher.matches(view.getParent());
}
ViewGroup group = (ViewGroup) view.getParent();
return parentMatcher.matches(view.getParent()) && view.equals(group.getChildAt(childPosition));
}
};
}
}
and this is my homefragment.xml file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:background="#color/black"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/promotionalviewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v4.view.ViewPager>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="#dimen/size_5"
android:gravity="center_horizontal">
<LinearLayout
android:id="#+id/viewPagerCountDots"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:orientation="horizontal" />
</RelativeLayout>
I hope it may help you to create a test case in Expresso Framework.
I am new to Android and am trying a sample application for showing ViewPagers in a Master-Detail Flow using custom PagerAdapters and FragmentStatePagerAdapters. My application has a list of dummy items managed by a SQLiteDatabase which contain a title String, a description String, a Boolean like status, and a list of images (I plan to implement them as downloading from String urls but presently I'm just trying with a single image resource). I am having two problems in the Detail View.
My intention is to use a ViewPager with a FragmentStatePagerAdapter to show the detail view, which consists of a ViewPager with a custom PagerAdapter for showing the list of images, TextView for title and description, a ToggleButton for the like status and a delete button for deleting items from the list.
Issues:
The ViewPager with the custom PagerAdapter does not display the image. It occupies the expected space and swipes performed on it also behave as expected. Only the image is not visible.
[RESOLVED] On using the delete button, I am able to delete the item from the database, and also update the Master View accordingly, but I am not able to update the Detail View, and the app crashes.
Here is my code:
Code that calls ItemDetailActivity.java
#Override
public void onClick(View v) {
Intent detailIntent = new Intent(getContext(), ItemDetailActivity.class);
detailIntent.putExtra(ItemDetailFragment.ARG_LIST_POSITION, holder.position);
getContext().startActivity(detailIntent);
}
ItemDetailActivity.java
public class ItemDetailActivity extends FragmentActivity {
static ItemDetailPagerAdapter idpa;
static ViewPager detailPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_detail);
idpa = new ItemDetailPagerAdapter(getSupportFragmentManager());
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
detailPager = (ViewPager) findViewById(R.id.item_detail_container);
detailPager.setAdapter(idpa);
detailPager.setCurrentItem(getIntent().getIntExtra(ItemDetailFragment.ARG_LIST_POSITION, 0));
}
}
activity_item_detail.xml
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/item_detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.trial.piclist.ItemDetailActivity"
tools:ignore="MergeRootFrame" />
ItemDetailFragment.java
public class ItemDetailFragment extends Fragment {
public static final String ARG_ITEM_ID = "item_id";
public static final String ARG_LIST_POSITION = "list_index";
public static final String ARG_TWO_PANE = "is_two_pane";
int position = -1;
long id = -1;
boolean twoPane = false;
ViewPager pager;
private PicItem mItem;
public ItemDetailFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
twoPane = getArguments().getBoolean(ARG_TWO_PANE, false);
position = getArguments().getInt(ARG_LIST_POSITION, -1);
id = getArguments().getLong(ARG_ITEM_ID, -1);
if (id == -1)
id = ItemListFragment.getIdByPosition(position);
setmItem(id);
}
public void setmItem(long id) {
if (id >= 0) {
try {
ItemListActivity.lds.open();
mItem = ItemListActivity.lds.getById(id);
ItemListActivity.lds.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
if (mItem != null) {
List<String> pics = new ArrayList<String>();
pics.add("1");
pics.add("2");
pics.add("3");
pics.add("4");
pics.add("5");
mItem.setPics(pics);
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_item_detail,
container, false);
DetailViewHolder holder = new DetailViewHolder();
pager = (ViewPager) rootView.findViewById(R.id.pager);
ImagePagerAdapter adapter = new ImagePagerAdapter(mItem, getActivity(),
inflater, position);
pager.setAdapter(adapter);
holder.position = getArguments().getInt(ARG_LIST_POSITION);
holder.ttv = (TextView) rootView.findViewById(R.id.item_title);
holder.dtv = (TextView) rootView.findViewById(R.id.item_detail);
holder.likeButton = (ToggleButton) rootView
.findViewById(R.id.item_like);
holder.deleteButton = (Button) rootView.findViewById(R.id.item_delete);
rootView.setTag(holder);
if (mItem != null) {
holder.ttv.setText(mItem.getTitle());
holder.dtv.setText(mItem.getDescription());
holder.likeButton.setChecked(mItem.getIsLiked());
holder.likeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ItemListActivity.lds.open();
ItemListActivity.lds.toggleLike(mItem.getId());
mItem.toggleIsLiked();
ItemListActivity.lds.close();
ItemListFragment.listDisplayHelper.toggleLiked(position);
}
});
holder.deleteButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ItemListActivity.lds.open();
ItemListActivity.lds.removeItem(mItem.getId());
ItemListActivity.lds.close();
ItemListFragment.listDisplayHelper.remove(position);
ItemListActivity.idpa.notifyDataSetChanged();
// What do I do so that the FragmentStatePagerAdapter is
// updated and the viewpager shows the next item.
}
});
}
return rootView;
}
static private class DetailViewHolder {
TextView ttv;
TextView dtv;
ToggleButton likeButton;
Button deleteButton;
int position;
}
}
fragment_item_detail.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context="com.trial.piclist.ItemDetailFragment" >
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="200dip">
</android.support.v4.view.ViewPager>
<TableRow
android:id="#+id/tableRow1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/item_title"
style="?android:attr/textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello"
android:textIsSelectable="true" />
<Space
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="#layout/controls_layout" />
</TableRow>
<ScrollView
android:id="#+id/descScrollView"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/item_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello" />
</LinearLayout>
</ScrollView>
</LinearLayout>
controls_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ToggleButton
android:id="#+id/item_like"
android:layout_width="30dip"
android:layout_height="30dip"
android:layout_gravity="right"
android:background="#android:drawable/btn_star"
android:gravity="center"
android:text="#string/like_list_item"
android:textOff="#string/empty_text"
android:textOn="#string/empty_text" />
<Button
android:id="#+id/item_delete"
style="?android:attr/buttonStyleSmall"
android:layout_width="30dip"
android:layout_height="30dip"
android:background="#android:drawable/ic_menu_delete"
android:text="#string/empty_text" />
</LinearLayout>
Custom PagerAdapter
ImagePagerAdapter.java
public class ImagePagerAdapter extends PagerAdapter {
LayoutInflater inflater;
List<View> layouts = new ArrayList<>(5);
// Constructors.
#Override
public Object instantiateItem(ViewGroup container, int position) {
if (layouts.get(position) != null) {
return layouts.get(position);
}
View layout = inflater.inflate(R.layout.detail_image,
((ViewPager) container), true);
try {
ImageView loadSpace = (ImageView) layout
.findViewById(R.id.detail_image_view);
loadSpace.setBackgroundColor(0x000000);
loadSpace.setImageResource(R.drawable.light_grey_background);
loadSpace.setAdjustViewBounds(true);
} catch (Exception e) {
System.out.println(e.getMessage());
}
layout.setTag(images.get(position));
layouts.set(position, layout);
return layout;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
#Override
public int getCount() {
return 5;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (((View) object).findViewById((view.getId())) != null);
}
}
FragmentPagerAdapter
ItemDetailPagerAdapter.java
public class ItemDetailPagerAdapter extends FragmentStatePagerAdapter {
public ItemDetailPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = new ItemDetailFragment();
Bundle args = new Bundle();
args.putLong(ItemDetailFragment.ARG_ITEM_ID, ItemListFragment.getIdByPosition(position));
args.putInt(ItemDetailFragment.ARG_LIST_POSITION, position);
args.putBoolean(ItemDetailFragment.ARG_TWO_PANE, ItemListActivity.mTwoPane);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
openDatabase();
int c = database.getCount();
closeDatabase();
return c;
}
#Override
public int getItemPosition(Object object) {
long mId = ((ItemDetailFragment) object).getmId();
int pos = POSITION_NONE;
openDatabase();
if (database.contains(mId)) {
pos = database.getPositionById(mId);
}
closeDatabase();
return pos;
}
}
Any help is much appreciated. Thanks :)
In your ItemDetailFragment, remove the viewpager from the holder, it should be directly into the returned view, something like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_item_detail,
container, false);
pager = (ViewPager) rootView.findViewById(R.id.pager);
ImagePagerAdapter adapter = new ImagePagerAdapter(mItem, getActivity(),inflater, position);
pager.setAdapter(adapter);
return rootView;
}
and the ViewHolder pattern should be applied inside your PagerAdapter.
In ImagePagerAdapter.java, correct the isViewFromObject method -
#Override
public boolean isViewFromObject(View view, Object object) {
return (view == (View) object);
}
This will correct the issue of the ImageView.
In ItemDetailPagerAdapter.java, override the getItemPosition method -
#Override
public int getItemPosition(Object object) {
int ret = POSITION_NONE;
long id = ((ItemDetailFragment) object).getId();
openDatabase();
if (databaseContains(id)) {
ret = positionInDatabase(id);
}
closeDatabase();
return ret;
}
On deleting call the FragmentStatePagerAdapter.NotifyDataSetChanged() method. This will make the Adapter update itself on deleting.
Although, the FragmentStatePagerAdapter uses a list of Fragments and of stored states to implement the adapter. That is also causing trouble. To remove that, implement your own list of Fragments.