I'm trying to get this working: I basically want two Recyclerviews in one ViewPager. I followed this Tutorial: http://android-java-development.blogspot.de/2012/05/system.html, but it doesn't seem to work. I looks like the view pager is empty and the recycler view doesn't show up.
Here's my layout code:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/pager_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="#dimen/tab_height">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/accent"/>
</android.support.v4.widget.SwipeRefreshLayout>
And my PageAdapter:
public class NewsPagerAdapter extends PagerAdapter {
private Context context;
private Vector<RecyclerView> recyclerViewList;
private String[] titles;
public NewsPagerAdapter(Context context, int titlesId) {
this.context = context;
this.recyclerViewList = new Vector<>();
setTitles(titlesId);
}
public void add(RecyclerView recyclerView) {
recyclerViewList.add(recyclerView);
}
public RecyclerView.Adapter getAdapterForViewAtIndex(int index) {
return recyclerViewList.get(index).getAdapter();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(recyclerViewList.get(position),
new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100)
);
return container;
}
#Override
public int getCount() {
return recyclerViewList.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
public void setTitles(int titles) {
this.titles = context.getResources().getStringArray(titles);
}
}
And my onCreatView method:
GridLayoutManager layoutManager1 = new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.news_column_count));
GridLayoutManager layoutManager2 = new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.news_column_count));
RecyclerView listView1 = new RecyclerView(getActivity());
RecyclerView listView2 = new RecyclerView(getActivity());
listView1.setLayoutManager(layoutManager1);
listView2.setLayoutManager(layoutManager2);
NewsAdapter adapter1 = new NewsAdapter(getActivity(), null);
NewsAdapter adapter2 = new NewsAdapter(getActivity(), null);
adapter1.setOnItemClickListener(this);
adapter2.setOnItemClickListener(this);
listView1.setAdapter(adapter1);
listView2.setAdapter(adapter2);
newsPagerAdapter.add(listView1);
newsPagerAdapter.add(listView2);
newsViewPager.setAdapter(newsPagerAdapter);
Here I'm passing the cursor object to the adapter:
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
((NewsAdapter) newsPagerAdapter.getAdapterForViewAtIndex(0)).swapCursor(data);
}
You have to extend FragmentPagerAdapter or FragmentStatePagerAdapter in order to easily embed RecyclerView. If you are going to update your ViewPager contents during its lifecycle it is strictly recommended to use FragmentStatePagerAdapter
You will have to create additional fragment layout, containing RecyclerView.
If you wish to update your ViewPager with SwipeRefreshLayout, don't wrap it with SwipeRefreshLayout. Instead, you must have SwipeRefreshLayout inside fragment layout.
Therefore for your fragment you may get the following xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/categoryList"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
And create additional Fragment class, which will inflate that layout and implement methods, that you will need to update refresh indicator status.
A bit old example is found here:
http://developer.android.com/training/implementing-navigation/lateral.html
If you wish to connect your ViewPager with new support library TabLayout, it is easily one with:
tabLayout.setupWithViewPager(viewPager);
Finally, if you will update your "fragmented" ViewPager, don't try to reset the adapter, as fragments are managed not with adapter, but with FragmentManager. It is wiser to update content of corresponding RecyclerViews
public class MyFragmentedPagerAdapter extends FragmentStatePagerAdapter {
private final TabLayout mTabLayout;
private final SwipeRefreshLayout.OnRefreshListener mRefreshListener;
private Vector<PriceListFragment> fragmentList;
private Vector<String> titles;
public MyFragmentedPagerAdapter(FragmentManager fm, MyComplexData data, OnCartActionListener listener, TabLayout tabLayout, SwipeRefreshLayout.OnRefreshListener refreshListener) {
super(fm);
mTabLayout = tabLayout;
// external refresh listener, that will trigger an updateData()
mRefreshListener = refreshListener;
fragmentList = new Vector<>();
titles = new Vector<>();
updateData(data);
}
public void updateData(MyComplexData data) {
boolean updateTabs = false;
boolean hasNewData = false;
Vector<String> newTitles = new Vector<>();
int position = 0;
for(TabContents tabContents : data.getTabContents()) {
if(tabContents.getListContents() == null)
continue;
hasNewData = true;
boolean isNewFragment;
MyFragment fragment;
try {
fragment = fragmentList.get(position);
isNewFragment = false;
} catch (ArrayIndexOutOfBoundsException e) {
fragment = new MyFragment();
isNewFragment = true;
}
// Update the data, title and hide update indicator of SwipeRefreshLayout
fragment.setTabContents(tabContents);
newTitles.add(tabContents.getName());
if(isNewFragment) {
fragment.setRefreshListener(mRefreshListener);
fragmentList.add(fragment);
}
position++;
}
if(!hasNewData)
return;
// we need to decide, whether to update tabs
if(titles.size() != newTitles.size()) {
updateTabs = true;
} else {
for(position = 0; position < titles.size(); position++) {
if(!titles.get(position).equals(newTitles.get(position))) {
updateTabs = true;
break;
}
}
}
titles = newTitles;
notifyDataSetChanged();
if(updateTabs)
mTabLayout.setTabsFromPagerAdapter(this);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
// You need to override this method as well
#Override
public int getItemPosition(Object object) {
MyFragment fragment = (MyFragment) object;
String title = (String) fragment.getTitle();
int position = titles.indexOf(title);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
#Override
public int getCount() {
return titles.size();
}
#Override
public CharSequence getPageTitle(int position) {
return fragmentList.get(position).getTitle();
}
}
Your MyFragment class has to implement getTitle() method.
Related
I want to display Fragments in a ViewPager however it is only showing the first Fragment in the view tabs. The only fragment that gets shown is the one returned at postion 0 in the getItem(0 method - this fragment is displayed in subsequent views.
FragmentPagerAdapter:
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
public SimpleFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new WorldFragment();
} else if (position == 1) {
return new PoliticsFragment();
} else if (position == 2) {
return new TechnologyFragment();
} else if (position == 3) {
return new ScienceFragment();
} else if (position == 4) {
return new SportsFragment();
} else if (position == 5) {
return new FoodFragment();
} else if (position == 6) {
return new TravelFragment();
} else if (position == 7) {
return new MoviesFragment();
} else if (position == 8) {
return new FashionFragment();
} else {
return new OpinionFragment();
}
}
#Override
public int getCount() {
return 10;
}
}
Fragment:
public class WorldFragment extends Fragment implements LoaderManager.LoaderCallbacks<List<Story>> {
public static final String LOG_TAG = WorldFragment.class.getName();
private static final String NY_TIMES_REQUEST_URL = "https://api.nytimes.com/svc/topstories/v2/world.json?api-key=<API KEY REMOVED>;
private StoryAdapter mAdapter;
private TextView mEmptyTextView;
private View rootView;
public WorldFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.story_list, container, false);
mAdapter = new StoryAdapter(getActivity(), new ArrayList<Story>());
final ListView listView = (ListView) rootView.findViewById(R.id.story_list);
mEmptyTextView = (TextView) rootView.findViewById(R.id.empty_textview);
listView.setEmptyView(mEmptyTextView);
listView.setAdapter(mAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Story currentStory = mAdapter.getItem(position);
String url = currentStory.getmURL();
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
});
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if (isConnected) {
LoaderManager loaderManager = getActivity().getLoaderManager();
loaderManager.initLoader(0, null, this);
} else {
View loadingIndicator = rootView.findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
mEmptyTextView = (TextView) rootView.findViewById(R.id.empty_textview);
mEmptyTextView.setText(R.string.no_internet_connection);
}
return rootView;
}
#Override
public android.content.Loader<List<Story>> onCreateLoader(int i, Bundle bundle) {
return new StoryLoader(getActivity(), NY_TIMES_REQUEST_URL);
}
#Override
public void onLoadFinished(android.content.Loader<List<Story>> loader, List<Story> stories) {
mAdapter.clear();
View loadingIndicator = rootView.findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
mEmptyTextView.setText(R.string.no_new_stories);
if (stories != null && !stories.isEmpty()) {
mAdapter.addAll(stories);
}
}
#Override
public void onLoaderReset(android.content.Loader<List<Story>> loader) {
mAdapter.clear();
}
#Override
public void onStop() {
super.onStop();
}
}
ViewPager XML:
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.topworldstories.MainActivity">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
List XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent">
<ListView
android:id="#+id/story_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="true" />
<TextView
android:id="#+id/empty_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
tools:text="No new stories"/>
<ProgressBar
android:id="#+id/loading_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true"/>
</LinearLayout>
I am unsure of what is causing this. Any help is appreciated
it is only showing the first Fragment multiple times in the view tabs
Two possibilities I see, both of which are copy-paste errors.
1) You didn't change this URL (notice world.json)
private static final String NY_TIMES_REQUEST_URL = "https://api.nytimes.com/svc/topstories/v2/world.json?api-key=<API KEY REMOVED>";
2) You didn't use a different layout.
rootView = inflater.inflate(R.layout.story_list, container, false);
But since your data seems to be consistent, I'm guessing #1 is true.
If you have 10 different URL's that you want to display in the same "fragment layout", you do not need 10 separate Fragment files.
For example, one Fragment
public class NyTimesFragment extends Fragment implements LoaderManager.LoaderCallbacks<List<Story>> {
public static final String LOG_TAG = NyTimesFragment.class.getName();
private static final String NY_TIMES_URL = "nyTimesURL";
private StoryAdapter mAdapter;
private TextView mEmptyTextView;
private View rootView;
public NyTimesFragment(String url) {
Bundle b = new Bundle();
b.putExtra(NY_TIMES_URL, url); // Pass URL here
setArguments(b);
}
public NyTimesFragment() {
// Required empty public constructor
}
#Override
public android.content.Loader<List<Story>> onCreateLoader(int i, Bundle bundle) {
// Load url here
String url = getArguments().getString(NY_TIMES_URL);
return new StoryLoader(getActivity(), url);
}
That you pass any NyTimes URL to
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
// List of NyTimes topics
private String[] topics = { "world", "politics" };
// !!! Do NOT store this in your app... !!!
private static final String API_KEY = "XXXXX";
public SimpleFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
private String getURL(String apiKey, String topic) {
return String.format(
"https://api.nytimes.com/svc/topstories/v2/%s.json?api-key=%s",
topic, apiKey);
}
#Override
public int getCount() {
return topics.length; // Assuming each fragment goes to NyTimes
}
#Override
public Fragment getItem(int position) {
final String url = getURL(topics[position], API_KEY);
// Call the other constructor
return new NyTimesFragment(url);
} // done... no if statements.
Something to consider to make this somewhat better would be Retrofit + Gson...
Ok so the issue here is I was using the same loader id in initloader for each fragment & this is why the same data was being loaded. The loader id needs to be unique for each fragment for this to work.
I am trying to pass an object that is retrieved and created during my main activities on create method to one of the fragments of my sliding tabs layout.
Since this object is created over a network connection my plan was to receive the data during the creation of the Main Activity then pass the resulting object to my fragments. However this seems easier said than done. The resulting object will then get passed to a recycler view in the Forecast fragment.
I have read various methods including implementing the parcelable interface on my model object, storing it as a bundle and trying to send it over to the fragment. However it always came up null. I believe this was due to me creating a new fragment in memory and not passing the bundle to the fragment that was displayed. I also don't have any ID's for the fragments so locating them by ID isn't possible, at least to my knowledge.
If anyone could point me in the right direction Id be greatly appreciative.
Main Activity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MAIN ACTIVITY";
#Bind(R.id.toolBar) Toolbar mToolbar;
#Bind(R.id.viewPager) ViewPager mViewPager;
#Bind(R.id.tabLayout) SlidingTabLayout mTabLayout;
private ViewPagerAdapter mAdapter;
private String mForecastsTabName = "Forecasts";
private String mAlertsTabName = "Alerts";
private String mTabTitles[] = {mForecastsTabName, mAlertsTabName};
private int mNumberOfTabs = 2;
private Forecast[] mForecasts;
private JsonParser mJsonParser = new JsonParser();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
setupSlidingTabs();
}
private void setupSlidingTabs() {
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
mAdapter = new ViewPagerAdapter(getSupportFragmentManager(), mTabTitles, mNumberOfTabs);
// Assigning the ViewPages View and setting the adapter
mViewPager.setAdapter(mAdapter);
// Assigning the Sliding Tab Layout View
mTabLayout.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Setting Custom Color for the Scroll bar indicator of the Tab View
mTabLayout.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.ColorAccent);
}
});
mTabLayout.setViewPager(mViewPager);
}
Forecast Fragment.java
public class ForecastFragment extends Fragment {
private static final String FORECAST_KEY = "FORECAST_KEY";
private static final String TAG = "FRAGMENT";
private Forecast[] mForecasts;
#Bind(R.id.recyclerView) RecyclerView mRecyclerView;
#Bind(R.id.emptyView) TextView mEmptyView;
#Bind(R.id.locationButton) Button mLocationButton;
public static ForecastFragment newInstance(Forecast[] forecasts) {
ForecastFragment fragment = new ForecastFragment();
Bundle bundle = new Bundle();
bundle.putParcelableArray(FORECAST_KEY, forecasts);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialize dataset, this data would usually come from a local content provider or
// remote server.
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.forecast_tab_fragment, container, false);
ButterKnife.bind(this, view);
displayEmptyViewIfNoData();
ForecastAdapter adapter = new ForecastAdapter(getActivity(), mForecasts);
mRecyclerView.setAdapter(adapter);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(layoutManager);
return view;
}
private void displayEmptyViewIfNoData() {
if (mForecasts == null || mForecasts.length < 1) {
mRecyclerView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
mLocationButton.setVisibility(View.VISIBLE);
}
else {
mRecyclerView.setVisibility(View.VISIBLE);
mEmptyView.setVisibility(View.GONE);
mLocationButton.setVisibility(View.GONE);
}
}
#OnClick(R.id.locationButton)
public void selectLocations(View view) {
Intent intent = new Intent(getActivity(), LocationSelectionActivity.class);
intent.putExtra(ActivityConstants.CALLING_ACTIVITY, ActivityConstants.FORECAST_ACTIVITY);
startActivity(intent);
}
}
ViewPagerAdapter.java
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
// This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
String mTitles[];
// Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
int mNumberOfTabs;
SparseArray<Fragment> registeredFragments = new SparseArray<>();
public ViewPagerAdapter(FragmentManager fm, String titles[], int numberOfTabs) {
super(fm);
mTitles = titles;
mNumberOfTabs = numberOfTabs;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if (position == 0) {
ForecastFragment forecastFragment = new ForecastFragment();
return forecastFragment;
}
else if (position == 1) {
AlertFragment alertFragment = new AlertFragment();
return alertFragment;
}
return null;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
#Override
public int getCount() {
return mNumberOfTabs;
}
}
Forecast_tab_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/ColorPrimaryLight">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_vertical_margin"/>
<TextView
android:id="#+id/emptyView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/empty_forecast_message"
android:textColor="#color/ColorTextPrimary"
android:gravity="center"
android:visibility="gone"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="115dp"/>
<Button
android:id="#+id/locationButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_shape"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:textColor="#color/ColorTextPrimary"
android:text="#string/add_forecast_button"
android:visibility="gone"
android:layout_alignParentBottom="false"
android:layout_centerHorizontal="true"
android:layout_below="#+id/emptyView"
android:layout_marginTop="24dp"/>
</RelativeLayout>
When you do this code below, you can hand the data to your fragment.
In your Activity, call below, when the data is ready:
mAdapter.getFragment(index).setData(dataObject);
or
mAdapter.getFragment(mViewPager.getCurrentItem()).setData(dataObject);
Your FragmentPagerAdater should be like this:
class CustomPagerAdapter extends FragmentPagerAdapter {
SparseArray<App4StoreBaseSubFragment> registeredFragments = new SparseArray<App4StoreBaseSubFragment>();
public CustomPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
App4StoreBaseSubFragment fragment = (App4StoreBaseSubFragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public ForecastFragment getFragment(int position){
return registeredFragments.get(position);
}
}
Your Fragment should be like this:
public class ForecastFragment extends Fragment {
public void setData(Forecast forecast){
//write code here to change UI
}
}
I have a tablayout, from android design support library:
compile 'com.android.support:design:23.0.1'
With this, I want to populate my tabs. But I'm failing to do that. I can create the tabs, but they fail to inflate their respective content:
Where it should have entries from LinearListView, an object similar to a ListView imported from this framework:
compile 'com.github.frankiesardo:linearlistview:1.0.1#aar'
I tried a great number of examples, but I failed to populate each tab. Any suggestions?
Code:
JAVA:
From main fragment:
OverviewTabLayoutPagerAdapter adapter = new OverviewTabLayoutPagerAdapter(getActivity().getSupportFragmentManager(), productDataContent, getContext());
ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewpager);
viewPager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
OverviewTabLayoutPagerAdapter:
public class OverviewTabLayoutPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "REVIEWS", "VIDEOS", "DEALS" };
private SearchContent productDataContent;
private Context context;
public OverviewTabLayoutPagerAdapter(FragmentManager fm, SearchContent productDataContent, Context context) {
super(fm);
this.productDataContent = productDataContent;
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
Log.i("TAB_POSITION", String.valueOf(position));
if (position == 0) {
return OverviewTab1Fragment.newInstance(position, productDataContent);
} else if (position == 1) {
return OverviewTab2Fragment.newInstance(position, productDataContent);
} else if (position == 2) {
return OverviewTab3Fragment.newInstance(position, productDataContent);
}
return OverviewTab1Fragment.newInstance(position, productDataContent);
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
OverviewTab*Fragment: (the * means the same code structure applies for every fragment):
public class OverviewTab*Fragment extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
public static final String PRODUCT_DATA_CONTENT = "PRODUCT_DATA_CONTENT";
private int mPage;
private SearchContent productDataContent;
public static OverviewTab*Fragment newInstance(int page, SearchContent productDataContent) {
OverviewTab*Fragment fragment = new OverviewTab*Fragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
args.putSerializable(PRODUCT_DATA_CONTENT, productDataContent);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
productDataContent = (SearchContent) getArguments().getSerializable(PRODUCT_DATA_CONTENT);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_tab_fragment, container, false);
LinearListView tabContentListView = (LinearListView) view.findViewById(R.id.product_content_linear_list_view);
populateOverviewTab*LinearLayout(tabContentListView, productDataContent);
return view;
}
private void populateOverviewTab*LinearLayout(LinearListView tabContentListView, SearchContent productDataContent) {
ArrayList<> productData = productDataContent.getContent();
OverviewTab*ArrayAdapter overviewTab*ArrayAdapter = new OverviewVideosArrayAdapter(
getContext(),
tabContentListView,
productData,
getActivity()
);
tabContentListView.setAdapter(overviewTab*ArrayAdapter);
...
XML:
From main fragment:
...
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/go_to_store_button"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
...
overview_tab_fragment.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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.linearlistview.LinearListView
android:id="#+id/product_content_linear_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:showDividers="end"
android:dividerPadding="5dp"
app:dividerThickness="2dp">
</com.linearlistview.LinearListView>
</RelativeLayout>
You can change:
#Override
public Fragment getItem(int position) {
Log.i("TAB_POSITION", String.valueOf(position));
if (position == 0) {
return OverviewTab1Fragment.newInstance(position, productDataContent);
} else if (position == 1) {
return OverviewTab2Fragment.newInstance(position, productDataContent);
} else if (position == 2) {
return OverviewTab3Fragment.newInstance(position, productDataContent);
}
return OverviewTab1Fragment.newInstance(position, productDataContent);
}
for this:
#Override
public Fragment getItem(int position) {
Log.i("TAB_POSITION", String.valueOf(position));
if (position == 0) {
return OverviewTab1Fragment.instantiate(context, productDataContent);
} else if (position == 1) {
return OverviewTab2Fragment.instantiate(context, productDataContent);
} else if (position == 2) {
return OverviewTab3Fragment.instantiate(context, productDataContent);
}
return OverviewTab1Fragment.instantiate(context, productDataContent);
}
UPDATE
This is an example with Fragment in Array:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.SparseArray;
import android.view.ViewGroup;
public class TabsViewPagerAdapter extends FragmentStatePagerAdapter {
private CharSequence titlesArray[]; // This will Store the Titles of the Tabs which are Going to be passed when TabsViewPagerAdapter is created
private Fragment tabsArray[];
private SparseArray<Fragment> registeredFragments;
// Build a Constructor and assign the passed Values to appropriate values in the class
public TabsViewPagerAdapter(FragmentManager fm, CharSequence titlesArray[], Fragment[] tabsArray) {
super(fm);
this.titlesArray = titlesArray;
this.tabsArray = tabsArray;
this.registeredFragments = new SparseArray<>();
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
return tabsArray[position];
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return titlesArray[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return titlesArray.length;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
In the Java you create the adapter:
String[] tabTitles = new String[]{"Tab1", "Tab2", "Tab3"};
Fragment[] tabsArray = new Fragment[]{new OverviewTab1Fragment(), new OverviewTab2Fragment(), new OverviewTab3Fragment()};
adapter = new TabsViewPagerAdapter(getSupportFragmentManager(), tabTitles, tabsArray);
And the fragment is something like this:
import android.support.v4.app.Fragment;
public class OverviewTab1Fragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.yourFragmentLayout, container, false);
return v;
}
}
I hope help you.
i'm having some issues implementing a Sliding Tabs activity that contains 2 Fragments and a Swipe Down to Refresh layout, namely implementing the Swipe Down to Refresh part (the rest is working just fine).
First here are my XML files.
The Main Activity XML , which contains the ViewPager wrapped in an SwipeRefreshLayout :
<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"
tools:context="com.example.popal.soul.MovieListActivityTEST">
<com.example.popal.soul.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
android:background="#color/ColorPrimary"/>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1">
</android.support.v4.view.ViewPager>
</android.support.v4.widget.SwipeRefreshLayout>
And the first tab XML , one of the 2 tabs (both are similar, so i`ll only post one)
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView
android:id="#+id/cardList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
Now, my main activity, which handles the ViewPager, Adapter an the SlidingTabsLayout.
public class MovieListActivityTEST extends AppCompatActivity {
ViewPager pager;
ViewPagerAdapter adapter;
SlidingTabLayout tabs;
CharSequence Titles[]={"Home","Events"};
int Numboftabs =2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_list_activity_test);
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true);
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
}
And finally, my fragment for the first Tab
public class Tab1 extends Fragment {
public MovieListAdapter movieListAdaptor;
public RecyclerView recycleList;
private SwipeRefreshLayout swipeContainer;
private List<MovieListAdapter.MovieDetails> movieList = new ArrayList<MovieListAdapter.MovieDetails>();
private ProgressBar progressBar;
private final static String MOVIES_POST_REQUEST ="//Long String, Edited out since it`s not relevant"
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1, container, false);
recycleList = (RecyclerView) v.findViewById(R.id.cardList);
progressBar = (ProgressBar) v.findViewById(R.id.progress_bar);
progressBar.setVisibility(View.VISIBLE);
swipeContainer = (SwipeRefreshLayout) v.findViewById(R.id.swipeContainer);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
recycleList.setLayoutManager(llm);
swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
movieListAdaptor.clear();
new Send_data_to_server().execute(MOVIES_POST_REQUEST);
swipeContainer.setRefreshing(false);
}
});
new Send_data_to_server().execute(MOVIES_POST_REQUEST);
return v;
}
The issue is, i'm getting a NULL Pointer Exception at swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {...} method, which i guess is because the Swipe-to-Refresh layout is in the main activity XML, and not the tabs fragment. So what is the proper way to implement this ? I also tried implementing a Swipe to refresh layout in one of the Tabs XML instead of wrapping the ViewPager in it, like above, but it would crash when swiping from tab to another.
Here`s the code from the entire fragment in Tab1, for tobs answer below
public class MoviesTabFragment extends Fragment implements Refreshable {
public MovieListAdapter movieListAdaptor;
public RecyclerView recycleList;
//private SwipeRefreshLayout swipeContainer;
public List<MovieListAdapter.MovieDetails> movieList = new ArrayList<MovieListAdapter.MovieDetails>();
public ProgressBar progressBar;
public final static String MOVIES_POST_REQUEST ="";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1, container, false);
recycleList = (RecyclerView) v.findViewById(R.id.cardList);
progressBar = (ProgressBar) v.findViewById(R.id.progress_bar);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
recycleList.setLayoutManager(llm);
new Send_data_to_server().execute(MOVIES_POST_REQUEST);
return v;
}
#Override
public void refresh() {
new Send_data_to_server().execute(MOVIES_POST_REQUEST);
}
public class Send_data_to_server extends AsyncTask<String, Void, String> {
private String data_poster;
private String data_fanart;
// protected void onPreExecute() {
// progressBar.setVisibility(View.VISIBLE);
// }
protected String doInBackground(String... params)
{
String jason_data = params[0];
HttpClient http_con = new HttpClient();
String output_from_server = http_con.establish_con(jason_data);
Log.i("DataFromServer", output_from_server);
JSONObject json_Obj = null;
JSONObject child_obj = null; //creating the "result" object in the main JSON Object
try {
json_Obj = new JSONObject(output_from_server);
child_obj = create_subObject("result", json_Obj);
JSONArray jsonArray = child_obj.optJSONArray("movies");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String title_data = jsonObject.optString("label").toString();
String plot_data = jsonObject.optString("plot").toString();
String year_data = jsonObject.optString("year").toString();
String movie_id_data = jsonObject.optString("movieid").toString();
String imdb_score = jsonObject.optString("rating").toString();
String imdb_score_short = imdb_score.substring(0, 3);
JSONObject child_obj2 = create_subObject("art", jsonObject);
data_poster = child_obj2.optString("poster").toString();
data_fanart = child_obj2.optString("fanart").toString();
JSONEncodePosterFanart encodePosterFanart = new JSONEncodePosterFanart();
String jason_dataPoster = encodePosterFanart.GetPosterFanartEncodedURL(data_poster);
String jason_dataFanart = encodePosterFanart.GetPosterFanartEncodedURL(data_fanart);
HttpClient http = new HttpClient();
String output_from_serverPoster = http.establish_con(jason_dataPoster);
HttpClient http2 = new HttpClient();
String output_from_serverFanart = http2.establish_con(jason_dataFanart);
JSONPosterFanart poster_fanart = new JSONPosterFanart();
String post_dl = poster_fanart.GetPosterFanart(output_from_serverPoster);
JSONPosterFanart poster_fanart2 = new JSONPosterFanart();
String fanart_dl = poster_fanart2.GetPosterFanart(output_from_serverFanart);
if (null == movieList) {
movieList = new ArrayList<MovieListAdapter.MovieDetails>();
}
MovieListAdapter.MovieDetails item = new MovieListAdapter.MovieDetails(title_data+" ("+year_data+")", post_dl, fanart_dl,plot_data,movie_id_data,imdb_score_short);
movieList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
return output_from_server;
}
protected void onPostExecute(String output_from_server) {
super.onPostExecute(output_from_server);
//progressBar.setVisibility(View.INVISIBLE);
movieListAdaptor = new MovieListAdapter(getActivity(), movieList);
recycleList.setAdapter(movieListAdaptor);
}
private JSONObject create_subObject(String tagName, JSONObject jObj) throws JSONException {
JSONObject subObj = jObj.getJSONObject(tagName); //getJSONObject returns the value from tagName (in our case jason_Obj that is being passed ar a param)
return subObj;
}
}
}
And the RecycleView adapter:
public class MovieListAdapter extends RecyclerView.Adapter<MovieListAdapter.MovieViewHolder> {
public List<MovieDetails> movieList;
private Context mContext;
public MovieListAdapter(Context mContext, List<MovieDetails> movieList) {
this.mContext = mContext;
this.movieList = movieList;
}
#Override
public int getItemCount() {
return movieList.size();
}
public void clear() {
movieList.clear();
notifyDataSetChanged();
}
#Override
public MovieViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.card_layout_movies_list, viewGroup, false);
return new MovieViewHolder(itemView);
}
#Override
public void onBindViewHolder(MovieViewHolder movieViewHolder, int i) {
MovieDetails mdet = movieList.get(i);
String fanart = "http://192.168.1.128/"+mdet.getImageViewFanart();
String poster = "http://192.168.1.128/"+mdet.getImageViewPoster();
Log.i("fanart", fanart);
Log.i("poster", poster);
movieViewHolder.vTitle.setText(mdet.Title);
Picasso.with(mContext).load(poster)
.resize(500, 746)
.error(R.drawable.poster_placeholder)
.placeholder(R.drawable.poster_placeholder)
.into(movieViewHolder.vPoster);
Picasso.with(mContext).load(fanart)
.resize(960, 540)
.error(R.drawable.fanart_placeholder)
.placeholder(R.drawable.fanart_placeholder)
.into(movieViewHolder.vFanart);
movieViewHolder.vplot = mdet.getPlot();
movieViewHolder.vmovie_id = mdet.getMovie_id();
}
public class MovieViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected TextView vTitle;
protected ImageView vPoster;
protected ImageView vFanart;
protected String vplot;
protected String vmovie_id;
protected String vimdb_score;
public MovieViewHolder(View v)
{
super(v);
vplot = new String();
vmovie_id = new String();
vimdb_score = new String();
vTitle = (TextView) v.findViewById(R.id.title);
vPoster = (ImageView) v.findViewById(R.id.imageViewPoster);
vFanart = (ImageView) v.findViewById(R.id.imageViewFanart);
v.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getLayoutPosition();
MovieDetails mov = movieList.get(position);
Intent intent = new Intent(mContext, MovieDetailsPageActivity.class);
Bundle bundle = new Bundle();
bundle.putString("movieid", mov.getMovie_id());
bundle.putString("plot", vplot);
bundle.putString("fanart_path", mov.getImageViewFanart());
bundle.putString("imdb_score", mov.getImdb_score());
intent.putExtras(bundle);
mContext.startActivity(intent);
}
}
public static class MovieDetails {
protected String Title;
protected String imageViewPoster;
protected String imageViewFanart;
protected String plot;
protected String movie_id;
protected String imdb_score;
public MovieDetails(String Title, String imageViewPoster,String imageViewFanart, String plot, String movie_id ,String imdb_score)
{
this.Title = Title;
this.imageViewPoster = imageViewPoster;
this.imageViewFanart = imageViewFanart;
this.plot = plot;
this.movie_id = movie_id;
this.imdb_score = imdb_score;
}
public String getTitle() {return Title;}
public String getImageViewPoster() {
return imageViewPoster;
}
public String getImageViewFanart() {
return imageViewFanart;
}
public String getPlot() {return plot;}
public String getMovie_id() {return movie_id;}
public String getImdb_score() {return imdb_score;}
}
}
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[];
int NumbOfTabs;
public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
#Override
public Fragment getItem(int position) {
if(position == 0)
{
MoviesTabFragment moviesTabFragment = new MoviesTabFragment();
return moviesTabFragment;
}
else
{
TVShowsTabFragment TVShowsTabFragment = new TVShowsTabFragment();
return TVShowsTabFragment;
}
}
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
#Override
public int getCount() {
return NumbOfTabs;
}
You're getting the NullPointerException because you inflate your fragment layout from R.layout.tab_1 which does not contain a SwipeRefreshLayout.
If you want the layout to be the parent of your ViewPager, I would recommend you to move your code which manages the RefreshLayout to the MainActivity:
public class MovieListActivityTEST extends AppCompatActivity {
ViewPager pager;
ViewPagerAdapter adapter;
SwipeRefreshLayout refreshLayout;
SlidingTabLayout tabs;
CharSequence Titles[]={"Home","Events"};
int Numboftabs =2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_list_activity_test);
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true);
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
// Assign your refresh layout
refreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeContainer);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Refreshable r = (Refreshable) adapter.getItemAt(pager.getCurrentItem());
r.refresh();
}
});
}
where each of your tab fragments implements a Refreshable interface:
public interface Refreshable {
void refresh();
}
and your adapter keeps track on all fragments:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
// list that keeps references to all attached Fragments
private SparseArray<Fragment> pages = new SparseArray<>();
...
public Fragment getItem(int position) {
Fragment f;
if(position == 0) {
...
} else { ... }
// add fragment to the list
pages.put(position, f);
}
public void destroyItem(ViewGroup container, int position, Object object) {
// remove fragment from list if it existed
if(pages.indexOfKey(position) >= 0) {
pages.remove(position);
}
super.destroyItem(container, position, object);
}
// return the attached Fragment that is associated with the given position
public Fragment getItemAt(int position) {
return pages.get(position);
}
}
I am having some trouble learning the ins and outs of the SQLite world. I have some code that is allowing me to enter data into a DB. But what i want to do is return this data into a listview. At the moment all I could figure out to do was to have each row printed in a toast after a new entry is added. Can someone please show me how to alter my code to print it in a listview? Or to even look at my code and see that i am going about it in the right way. Thanks
This is the code i am using which calls a display record function
//---get all Records---
com.example.rory.dbtest.DBAdapter db = new com.example.rory.dbtest.DBAdapter(this);
db.open();
Cursor c = db.getAllRecords();
if (c.moveToFirst())
{
do {
DisplayRecord(c);
} while (c.moveToNext());
}
db.close();
This is the display record function
public void DisplayRecord(Cursor c)
{
Toast.makeText(this,
"id: " + c.getString(0) + "\n" +
"Item: " + c.getString(1) + "\n" +
"Litres: " + c.getString(2),
Toast.LENGTH_SHORT).show();
}
I know i need to change the second function but i dont know how to do that to make it print into a listview
this is the code of getting data from database and insert into Arraylist and insert into arrayAdapter and than display it in listview .
i just done some editing in your existing code.
com.example.rory.dbtest.DBAdapter db = new com.example.rory.dbtest.DBAdapter(this);
db.open();
ArrayList<String> data_list=new ArrayList<String>();
ListView lv=(ListView)findViewById(R.id.listView1);
Cursor c = db.getAllRecords();
if (c.moveToFirst())
{
do {
data_list.add(c.getString(0));
DisplayRecord(c);
} while (c.moveToNext());
}
ArrayAdapter<String> aa=new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, data_list);
lv.setAdapter(aa);
lv - is the object of ListView.
Create a ListView. Then provide cursorAdapter to the ListView as it's adapter to bind the data in the database to the ListView.
There are examples in the samples folder of the SDK you downloaded in the project called ApiDemos.
You need to have, 1) listview, 2) Object class, 3) Custom Adapter
Here I have just tried to implement as per your requirement.
Since I dont have db I did not try to run. The point to is to five you idea.
Because listview is widget that we use more frequently in android. This is the best approach as per my knowledge.
Layouts that required,
activity_list.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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".ListActivity" >
<ListView
android:id="#+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</RelativeLayout>
row_item.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="vertical"
android:padding="10dp" >
<TextView
android:id="#+id/Item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item" />
<TextView
android:id="#+id/Litres"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="litres" />
</LinearLayout>
ListActivity.java :
public class ListActivity extends Activity {
ArrayList<RowData> rowDataArrayList = new ArrayList<RowData>();
ListView list;
ListAdapter listAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
list = (ListView) findViewById(R.id.list);
listAdapter = new ListAdapter(ListActivity.this, rowDataArrayList);
list.setAdapter(listAdapter);
getDataFromDB();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list, menu);
return true;
}
private void getDataFromDB() {
rowDataArrayList.clear();
com.example.rory.dbtest.DBAdapter db = new com.example.rory.dbtest.DBAdapter(
this);
db.open();
Cursor c = db.getAllRecords();
if (c.moveToFirst()) {
do {
/**
* Set your data in class
*/
RowData rowData = new RowData();
rowData.setId(c.getString(0));
rowData.setItem(c.getString(1));
rowData.setLitres(c.getString(2));
rowDataArrayList.add(rowData);
} while (c.moveToNext());
}
db.close();
/**
* To reflect new data set change in listview
*/
listAdapter.notifyDataSetChanged();
}
}
RowData.java : Model[pojo] class to save data and to bind in custom adapter.
public class RowData {
String Id;
String Item;
String Litres;
public String getId() {
return Id;
}
public void setId(String id) {
Id = id;
}
public String getItem() {
return Item;
}
public void setItem(String item) {
Item = item;
}
public String getLitres() {
return Litres;
}
public void setLitres(String litres) {
this.Litres = litres;
}
}
ListAdapter.java : custom adapter to bind in listview
public class ListAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<RowData> rowDataArrayList = new ArrayList<RowData>();
public ListAdapter(Context context, ArrayList<RowData> rowData) {
mContext = context;
rowDataArrayList = rowData;
}
#Override
public int getCount() {
return rowDataArrayList == null ? 0 : rowDataArrayList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
Holder holder = new Holder();
view = View.inflate(mContext, R.layout.row_item, null);
holder.tvtItem = (TextView) view.findViewById(R.id.Item);
holder.tvtLitres = (TextView) view.findViewById(R.id.Litres);
view.setTag(holder);
} else {
view = convertView;
}
Holder holder = (Holder) view.getTag();
holder.tvtItem.setText(rowDataArrayList.get(position).getItem());
holder.tvtLitres.setText(rowDataArrayList.get(position).getLitres());
return view;
}
class Holder {
TextView tvtItem;
TextView tvtLitres;
}
}
public class ListAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<RowData> rowDataArrayList = new ArrayList<RowData>();
public ListAdapter(Context context, ArrayList<RowData> rowData) {
mContext = context;
rowDataArrayList = rowData;
}
#Override
public int getCount() {
return rowDataArrayList == null ? 0 : rowDataArrayList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
Holder holder = new Holder();
view = View.inflate(mContext, R.layout.row_item, null);
holder.tvtItem = (TextView) view.findViewById(R.id.Item);
holder.tvtLitres = (TextView) view.findViewById(R.id.Litres);
view.setTag(holder);
} else {
view = convertView;
}
Holder holder = (Holder) view.getTag();
holder.tvtItem.setText(rowDataArrayList.get(position).getItem());
holder.tvtLitres.setText(rowDataArrayList.get(position).getLitres());
return view;
}
class Holder {
TextView tvtItem;
TextView tvtLitres;
}
}