I have problems with implementation of my custom PagerAdapter and using it with a ViewPager.
This sample PagerAdapter has 10 items, every item is a button with it's index as text.
When I run my program, I see a button with text '1' insted of '0'. And when I swipe to other items I get only blank views. When I swipe backwards sometimes I see a button with some number, but it disappears (maybe it is destroying and I remove it from the container), and sometimes I see a button with a number, but the number changes after the swipe (I think I create a new Button and I add it to the container, and for some reasons the viewpager shows this new button).
How can I fix this implementation? I haven't seen difference in examples.
My PagerAdapter implementation:
public class MyPagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return 10;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return o.getClass()==view.getClass();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Button button = new Button(container.getContext());
ViewGroup.LayoutParams params = new ActionBar.LayoutParams(-1,-1);
button.setLayoutParams(params);
button.setText(String.valueOf(position));
container.addView(button);
return button;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((Button)object);
}
}
And my Activity:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new MyPagerAdapter());
}
}
Here is complete code:
xml layout:
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androidviewpagerapp.MainActivity" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
MyPagerAdapter class:
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
public class MyPagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return 10;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return o==view;
}
#Override
public Object instantiateItem(final ViewGroup container, int position) {
Button button = new Button(container.getContext());
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
button.setText(String.valueOf(position));
final int page = position;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(container.getContext(), "You clicked: " + page + ". page.", Toast.LENGTH_SHORT).show();
}
});
container.addView(button);
return button;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((Button)object);
}
}
MainActivity:
import android.support.v4.view.ViewPager;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
ViewPager viewPager;
MyPagerAdapter myPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager)findViewById(R.id.pager);
myPagerAdapter = new MyPagerAdapter();
viewPager.setAdapter(myPagerAdapter);
}
}
You will see that Buttons are full screen. To avoid that you need to create some layout (like LinearLayout) and add button to that layout.
Example:
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
public class MyPagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return 10;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return o==view;
}
#Override
public Object instantiateItem(final ViewGroup container, int position) {
Button button = new Button(container.getContext());
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
button.setText(String.valueOf(position));
LinearLayout layout = new LinearLayout(container.getContext());
layout.setOrientation(LinearLayout.VERTICAL);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//add buton to layout
layout.addView(button);
final int page = position;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(container.getContext(), "You clicked: " + page + ". page.", Toast.LENGTH_SHORT).show();
}
});
//to container add layout instead of button
container.addView(layout);
//return layout instead of button
return layout;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
//cast to LinearLayout
container.removeView((LinearLayout)object);
}
}
if you want to inflate views in pager you must have to implement two methods.
instantiateItem and destroyItem
public class DialogPagerAdapter extends PagerAdapter {
private Context mContext;
//view inflating..
#Override
public Object instantiateItem(ViewGroup collection, int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.account_dialog_signin_viewpagers,
collection, false);
TextView tvLabel = (TextView) layout.findViewById(R.id.textView);
switch (position) {
case 0:
tvLabel.setText("Log In");
tvLabel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
break;
case 1:
tvLabel.setText("Sign Up");
tvLabel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
break;
case 2:
tvLabel.setText("Send Reset Link");
tvLabel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//onOptionClickForgot.OnOptionClick();
}
});
break;
}
collection.addView(layout);
return layout;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
#Override
public int getCount() {
return 3;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
Simply call it like
viewPager.setAdapter(new DialogPagerAdapter);
xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/dialog_button_height"
android:paddingLeft="#dimen/dimen_2"
android:paddingRight="#dimen/dimen_2"
android:minHeight="#dimen/dialog_button_height">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center"
android:text="#string/app_name"
android:textColor="#color/white"
android:textSize="#dimen/text_size_medium" />
</RelativeLayout>
Here i post ViewPagerAdapter that attached between TabLayout to ViewPager
public class ViewPagerAdapter extends FragmentPagerAdapter {
ArrayList<String> titleList = new ArrayList<>();
List<Fragment> fragment = new ArrayList<>();
public void addFragment(String title, Fragment fragment) {
this.titleList.add(title);
this.fragment.add(fragment);
}
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#NonNull
#Override
public Fragment getItem(int position) {
return fragment.get(position);
}
#Override
public int getCount() {
return titleList.size();
}
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}
}
How to use ViewPagerAdapter.
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment("TAB 1", new YOUR_FRAGMENT1());
adapter.addFragment("TAB 2", new YOUR_FRAGMENT2());
// Keep adding fragments.
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
Related
I'm trying to let my ViewPager to show my Fragments, however, it doesn't seem to do the work. All it does is just not showing anything, not even a height. Can someone tell me what step am I missing? thanks
main_activity.xml:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorBackground">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottomNavigation" />
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="#+id/bottomNavigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</android.support.design.widget.CoordinatorLayout>
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
AHBottomNavigation bottomNavigation;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigation = (AHBottomNavigation) findViewById(R.id.bottomNavigation);
viewPager = (ViewPager) findViewById(R.id.viewpager);
ViewPagerAdapter pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
// Buttom Navigation
// Add items
AHBottomNavigationItem item1 = new AHBottomNavigationItem("Rooms", R.drawable.ic_chatboxes);
AHBottomNavigationItem item2 = new AHBottomNavigationItem("User", R.drawable.ic_contact_outline);
bottomNavigation.addItem(item1);
bottomNavigation.addItem(item2);
// Customize Buttom Navigation
bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);
// Set colors
bottomNavigation.setAccentColor(ContextCompat.getColor(this, R.color.colorAccent));
bottomNavigation.setInactiveColor(ContextCompat.getColor(this, R.color.colorTabDefault));
// Set background color
bottomNavigation.setDefaultBackgroundColor(ContextCompat.getColor(this, R.color.colorBackground));
bottomNavigation.setTranslucentNavigationEnabled(true);
// Viewpager setup
pagerAdapter.addFragment(new Rooms(), "Rooms");
pagerAdapter.addFragment(new User(), "User");
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(bottomNavigation.getCurrentItem());
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
bottomNavigation.setCurrentItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
#Override
public boolean onTabSelected(int position, boolean wasSelected) {
viewPager.setCurrentItem(position, true);
return true;
}
});
}
ViewPagerAdapter.java:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
private Fragment currentItem;
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentItem() != object) {
currentItem = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
public Fragment getCurrentItem() {
return currentItem;
}
}
I have got some weird problem after implementing multiple instance(loaded dynamically depending on the data) of same fragment inside a Viewpager.
My fragment class consists of a listview which will be populated according to the data retrieved from the server, but every time i swipe page from one to another, the data inside a listview of the fragment is jumbled.
Here is the code. Any help will be appreciated. Thank You.
This the Fragment class where the Viewpager is present.
public class Menu extends Fragment implements View.OnClickListener {
private SlidingTabLayout mSlidingTab;
SlidingUpPanelLayout mLayout;
private ArrayList<String> menu_names;
private ViewPager pager;
ActionBarActivity act;
public ArrayList<ArrayList<All_Data>> menus;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.main, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
mSlidingTab = (SlidingTabLayout) act.findViewById(R.id.sliding_tab);
mSlidingTab.setDistributeEvenly(true);
mSlidingTab.setCustomTabView(R.layout.custom_text, 0);
pager= (ViewPager) act.findViewById(R.id.pager);
mSlidingTab.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return android.R.color.transparent;
}
});
mSlidingTab.bringToFront();
menuUpdate();
}
class MyPagerAdapter extends FragmentStatePagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return Meals.newInstance(position);
}
#Override
public int getCount() {
return menu_names.size();
}
#Override
public CharSequence getPageTitle(int i) {
return menu_names.get(i);
}
}
private void menuUpdate(String result) {
//menu_names= List Retrieved from server
//menus= List Retrieved from server
pager.setAdapter(new MyPagerAdapter(act.getSupportFragmentManager()));
mSlidingTab.setViewPager(pager);
}
Meals.java(Fragment class):
public class Meals extends Fragment {
ActionBarActivity activity;
int position = 0;
static Meals newInstance(int page) {
Meals fragmentFirst = new Meals();
Bundle args = new Bundle();
args.putInt("position", page);
fragmentFirst.setArguments(args);
return fragmentFirst;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.meals, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
position = getArguments().getInt("position");
ArrayList<All_Data> mMeals;
Fragment menu = activity.getSupportFragmentManager().findFragmentByTag("Menu");
mMeals = ((Menu) menu).menus.valueAt(position);
ListView mList = (ListView) activity.findViewById(R.id.mainMenu1);
LayoutInflater inflater;
inflater = LayoutInflater.from(activity.getApplicationContext());
mList.addHeaderView(inflater.inflate(R.layout.custom_text, mList, false));
mList.addFooterView(inflater.inflate(R.layout.footer, mList, false));
Menu_adapter adapter = new Menu_adapter(((Menu) menu), mMeals, activity);
mList.setAdapter(adapter);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
activity = (ActionBarActivity) context;
}
#Override
public void onResume() {
super.onResume();
MyApplication.getInstance().trackScreenView("Startes Screen");
}
}
meals.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="#f1f2f3"
android:orientation="vertical">
<ListView
android:id="#+id/mainMenu1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#f1f2f3"
android:dividerHeight="20dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:scrollbars="none" />
</RelativeLayout>
I'm trying to make it so when the user taps an image, a Toast pops up with the relevant name. I think I need to do this with a switch statement since I have an array, but am unsure if that's actually the correct way.
Here's my code:
public class MainActivity extends AppCompatActivity {
Integer[] Family = {R.drawable.angelica, R.drawable.dad, R.drawable.enzoandbully, R.drawable.enzokathyalex, R.drawable.ernesto, R.drawable.gale, R.drawable.joel, R.drawable.lorenzo};
ImageView pic;
Integer member;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView grid = (GridView) findViewById(R.id.gridView);
final ImageView pic = (ImageView) findViewById(R.id.imgFamily);
grid.setAdapter(new ImageAdapter(this));
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getBaseContext(), " " + (position + 1), Toast.LENGTH_SHORT).show( );
pic.setImageResource(Family[position]);
}
});
}
public class ImageAdapter extends BaseAdapter {
private Context context;
public ImageAdapter(Context c) {
context = c;
}
#Override
public int getCount() {
return Family.length;
}
#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) {
pic = new ImageView(context);
pic.setImageResource(Family[position]);
pic.setScaleType(ImageView.ScaleType.FIT_XY);
pic.setLayoutParams(new GridView.LayoutParams(330,300));
return pic;
}
}
}
Edit: Forgot XML Code:
<GridLayout 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:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp" tools:context=".MainActivity">
<GridView
android:layout_width="wrap_content"
android:layout_height="300dp"
android:id="#+id/gridView"
android:numColumns="2"
android:columnWidth="160dp"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:gravity="center" />
<ImageView
android:id="#+id/imgFamily"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_gravity="center_horizontal"
android:contentDescription="#string/imgFamily"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_row="12"
android:layout_column="0" />
</GridLayout>
Hope this should work.
Create a model class that will hold the name and image of the family member like this one -
public class FamilyMember {
private String name;
private int imageResource;
public FamilyMember(String name, int imageResource) {
this.name = name;
this.imageResource = imageResource;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImageResource() {
return imageResource;
}
public void setImageResource(int imageResource) {
this.imageResource = imageResource;
}
}
And your activity should like this one -
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;
// please use the correct R
import com.sample.R;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
List<FamilyMember> members = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
members = getFamilyMember();
setContentView(R.layout.activity_main);
GridView grid = (GridView) findViewById(R.id.gridView);
final ImageView pic = (ImageView) findViewById(R.id.imgFamily);
grid.setAdapter(new ImageAdapter(this));
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FamilyMember member = members.get(position);
Toast.makeText(MainActivity.this, member.getName(), Toast.LENGTH_SHORT).show( );
pic.setImageResource(member.getImageResource());
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class ImageAdapter extends BaseAdapter {
private Context context;
public ImageAdapter(Context c) {
context = c;
}
#Override
public int getCount() {
return members.size();
}
#Override
public Object getItem(int position) {
return members.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
FamilyMember member = (FamilyMember) getItem(position);
pic = new ImageView(context);
pic.setImageResource(member.getImageResource());
pic.setScaleType(ImageView.ScaleType.FIT_XY);
pic.setLayoutParams(new GridView.LayoutParams(330,300));
return pic;
}
}
private List<FamilyMember> getFamilyMember() {
List<FamilyMember> members = new ArrayList<>();
members.add(new FamilyMember("Angelica", R.drawable.R.drawable.angelica));
members.add(new FamilyMember("Dad", R.drawable.R.drawable.dad));
// like the above add the family members here
return members;
}
}
int id = item.getItemId();
switch (item.getItemId()) {
case R.id.action_add_faculty:
// EITHER CALL THE METHOD HERE OR DO THE FUNCTION DIRECTLY
Toast.makeText(Cureent.this,"You clicked yes button",Toast.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Change according to your requirement .hope it will work.
Do it this way:
public class MainActivity extends AppCompatActivity {
int[] Family = {R.drawable.angelica, R.drawable.dad, R.drawable.enzoandbully, R.drawable.enzokathyalex, R.drawable.ernesto, R.drawable.gale, R.drawable.joel, R.drawable.lorenzo};
ImageView pic;
int member;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView grid = (GridView) findViewById(R.id.gridView);
final ImageView pic = (ImageView) findViewById(R.id.imgFamily);
grid.setAdapter(new ImageAdapter(this));
grid.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int iden = view.getId();
switch(iden) {
case R.id.gridView:
Toast.makeText(MainActivity.this, String.valueOf(position + 1), Toast.LENGTH_SHORT).show();
pic.setImageResource(Family[position]);
break;
default:
break;
}
}
public class ImageAdapter extends BaseAdapter {
private Context context;
public ImageAdapter(Context c) {
context = c;
}
#Override
public int getCount() {
return Family.length;
}
#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) {
pic = new ImageView(context);
pic.setImageResource(Family[position]);
pic.setScaleType(ImageView.ScaleType.FIT_XY);
pic.setLayoutParams(new GridView.LayoutParams(330,300));
return pic;
}
}
}
Hope this helps. Please comment if you have any questions.
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.