Why ViewPager is slow - java

I'm using ViewPager to swipe between multiple images, but swiping between images is sluggish and not smooth although i only loaded few images. Here's my full code
MainActivity.java
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
public static SectionsPagerAdapter mSectionsPagerAdapter;
public static ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
Bundle args = new Bundle();
fragment = new Page();
args.putString(Page.ARG_SECTION_NUMBER, position);
fragment.setArguments(args);
return fragment;
}
public int getItemPosition(Object object) {
Log.v("MBG", "getItemPosition");
return POSITION_NONE;
}
#Override
public int getCount() {
return 6;
}
}
Page.java
public class Page extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
public Page() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_page, container, false);
String index = getArguments().getString(ARG_SECTION_NUMBER);
ImageView callImage = (ImageView) rootView.findViewById(R.id.imageView);
int resID = getActivity().getResources().getIdentifier(index, "drawable", getActivity().getPackageName());
callImage.setImageResource(resID);
return rootView;
}
MainActivity.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_marginTop="0dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Prayers"
/>
</RelativeLayout>
Page.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.mahmoud.qaloun.Page">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageView"
android:src="#drawable/a1"
android:scaleType="fitXY"
/>
</RelativeLayout>
But when i change this line of code
int resID = getActivity().getResources().getIdentifier(index, "drawable", getActivity().getPackageName());
to this:
int resID = getActivity().getResources().getIdentifier("1", "drawable", getActivity().getPackageName());
it works fine where "1" is an image stored in the resources folder "1.jpg"

Put
mViewPager.setOffscreenPageLimit(5);
after mViewPager.setAdapter();
Replace 5 with the number of pages that are off screen, i.e. total number of pages minus 1.
This will make your ViewPager smooth.
The reason why ViewPager is slow without this is that any page which is off screen gets destroyed and is recreated every time you switch to that page. If you have time consuming code in your Fragment's onActivityCreated(), they're going to be executed on every page switch. If you set the off screen page limit right, your Fragments will not be recreated every time you switch pages.

In my case - I have more then 10 images and each image have weight more 800kb, and I check this issue, and realy fine work if pass as a parameter 3 page
viewPager.setOffscreenPageLimit(3);
Also if you store your images in res/drawable - rename drawable to drawable-nodpi, because -nodpi mean next
These are density-independent resources. The system does not scale
resources tagged with this qualifier, regardless of the current
screen's density.

I too had the same problem. Please resize your image to smaller or required size. This will be a solution to your problem.

Related

Unwanted top margin when using ViewPager2 with TabLayout

I have a TabLayout with a ViewPager2 attached.
I attach my fragments to it like normal but I have an odd behaviour.
Between the TabLayout and the TextView there is some kind of gap although my Textview should be in the very top left corner. I cannot figure out where this extra margin is coming from (It does not matter what kind of view I place into the fragment it seems the whole fragment is shifted down (But the actual background of my fragment covers the entire ViewPager area)
This is the code for the viewPager und TabLayout.
<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">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
tools:background="?attr/colorPrimary"
app:tabGravity="fill"
app:tabIndicatorColor="?attr/colorSecondary"
app:tabIndicatorFullWidth="false"
app:tabIndicatorHeight="3dp"
app:tabMinWidth="48dp"
app:tabMode="fixed"
app:tabSelectedTextColor="?attr/colorOnPrimary"
app:tabTextAppearance="#style/App.Tab.Text"
app:tabTextColor="?attr/colorPrimaryLight"/>
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:background="#color/lightRed"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
I only added the background color to see which view is "below" the margin
This is the code for the fragment.
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/lightOrange"
android:fitsSystemWindows="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NO MARGIN TOP LEFT"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Where does my margin come from? It drives me nuts. I do not change margins inside the code whatsoever.
I use a custom FragmentStateAdapter which might be the culprit? On a sidenot the first click on a tab after the app opens will not switch the page, I could not make this work yet any idea why?
Here is the Adapter I use:
public class TabAdapter extends FragmentStateAdapter {
private static final String TAG = "TabAdapter";
private final List<TabFragment> mFragments;
private final String prefix;
private final ViewPager2 mViewPager;
private final TabLayout mTabLayout;
private final OnPageChangeCallback callback;
public interface OnPageChangeCallback {
void onPageSelected(int position);
}
public TabAdapter(BaseFragment fragment, TabLayout tabLayout, ViewPager2 viewPager, TabFragment... fragments) {
this(fragment, tabLayout, viewPager, Arrays.asList(fragments), null);
}
public TabAdapter(BaseFragment fragment, TabLayout tabLayout, ViewPager2 viewPager, List<TabFragment> fragments) {
this(fragment, tabLayout, viewPager, fragments, null);
}
public TabAdapter(BaseFragment fragment, TabLayout tabLayout, ViewPager2 viewPager, List<TabFragment> fragments, OnPageChangeCallback listener) {
super(fragment);
this.mFragments = fragments;
this.prefix = fragment.TAG;
this.mViewPager = viewPager;
this.mTabLayout = tabLayout;
this.callback = listener;
initTabLayout();
}
#Override
#NonNull
public BaseFragment<?> createFragment(int position) {
return mFragments.get(position).getFragment();
}
#Override
public long getItemId(int position) {
return Objects.hash(mFragments.get(position));
}
#Override
public boolean containsItem(long itemId) {
for (TabFragment fragment : mFragments) {
if (Objects.hash(fragment) == itemId) return true;
}
return false;
}
#Override
public int getItemCount() {
return mFragments.size();
}
private void initTabLayout() {
mViewPager.setAdapter(this);
mViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (callback != null) callback.onPageSelected(position);
TabStateProvider.saveTab(prefix, position);
}
});
int startTab = TabStateProvider.getTab(prefix, false, 0);
new TabLayoutMediator(mTabLayout, mViewPager, (tab, position) -> {
tab.setText(mFragments.get(position).getTabTitle());
}).attach();
selectPage(startTab);
}
void selectPage(int pageIndex) {
mViewPager.post(() -> {
mViewPager.setCurrentItem(pageIndex, false);
});
}
}

How to change the layout with different markup when device rotation?

Description
I have one activity in the vertical orinentation with two tabs (TabLayout) and fragments, which change with Viewpager.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
// Assign created adapter to viewPager
viewPager.setAdapter(new TabsExamplePagerAdapter(getSupportFragmentManager()));
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
// This method setup all required method for TabLayout with Viewpager
tabLayout.setupWithViewPager(viewPager);
}
public class TabsExamplePagerAdapter extends FragmentPagerAdapter {
// As we are implementing two tabs
private static final int NUM_ITEMS = 2;
public TabsExamplePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
// For each tab different fragment is returned
public Fragment getItem(int position) {
switch (position) {
case 0:
return new TabOneFragment();
case 1:
return new TabTwoFragment();
default:
return null;
}
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public CharSequence getPageTitle(int position) {
return "Tab " + (position + 1);
}
}
}
activity_main.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:tabTextColor="#ffffff"
app:tabIndicatorColor="#fbff3a"
app:tabSelectedTextColor="#fbff3a"
app:tabIndicatorHeight="5dp"
android:elevation="4dp"
app:tabGravity="fill"
app:tabMaxWidth="0dp" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
In each tabs i have for one fragments.
TabOneFragment.java (TabTwoFragment is similar ):
public class TabOneFragment extends Fragment {
// Required empty public constructor
public TabOneFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_tab_one, container, false);
}
}
fragment_one_tab.xml (fragment_one_tab.xml is similar)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="innovatecode.com.tabexample.TabOneFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="18dp"
android:text="#string/tab_one" />
</FrameLayout>
And i have simply result:
My problem
When my device is rotated to the horizontal position, I want to get the following result:
I create xml for horizontal markup (land):
active_main.xml (land)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/fragment_left"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
<FrameLayout
android:id="#+id/fragment_right"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
But I don't know how to change my code to get this result. I'm not very strong in working with fragments.
First, you can improve your landscape layout by adding your fragments directly to the layout file (under "res/layout-land"):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:name="innovatecode.com.tabexample.TabOneFragment"
android:id="#+id/fragment_left"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment
android:name="innovatecode.com.tabexample.TabTwoFragment"
android:id="#+id/fragment_right"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
You can read move on the topic here.
For the code part, you could make use of distinct features of your landscape and portrait layouts to switch between the corresponding logic in code. For example:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.tab_layout) != null) {
setUpPortraitLayout();
} else {
setUpLandscapeLayout();
}
}
private void setUpPortraitLayout() {
ViewPager viewPager = findViewById(R.id.pager);
// Assign created adapter to viewPager
viewPager.setAdapter(new TabsExamplePagerAdapter(getSupportFragmentManager()));
TabLayout tabLayout = findViewById(R.id.tab_layout);
// This method setup all required method for TabLayout with Viewpager
tabLayout.setupWithViewPager(viewPager);
}
private void setUpLandscapeLayout() {
// Note: with the layout definition suggested above you don't
// need any manual processing to set-up your layout for landscape
// but you still may have some extra set-up (initial binding, etc).
tabOneFragment = (TabOneFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_left);
tabTwoFragment = (TabTwoFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_right);
// ...
}
}
You can pass saved parameters to your fragments via "setArguments()" method. Alternatively consider using "onSaveInstanceState()" methods of your fragments (as opposed to activity, which you use now).
Alternative approach: dynamically add fragments in both landscape and portrait cases. It is based on your code. I think some aspects are arguable (I may be wrong), but changing direction would mean rewriting the whole thing. But it should work eventually.
res/layout-land/active_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/fragment_left"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<FrameLayout
android:id="#+id/fragment_right"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
MainActivity.java (based off the code you shared via gist)
public class MainActivity extends AppCompatActivity {
private Fragment tabOneFragment;
private Fragment tabTwoFragment;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
//Restore the fragment's instance
tabOneFragment = (TabOneFragment) getSupportFragmentManager().getFragment(
savedInstanceState, "tabOneFragment");
tabTwoFragment = (TabTwoFragment) getSupportFragmentManager().getFragment(
savedInstanceState, "tabTwoFragment");
} else {
tabOneFragment = new TabOneFragment();
tabTwoFragment = new TabTwoFragment();
}
if (findViewById(R.id.tab_layout) != null) {
setUpPortraitLayout();
} else {
setUpLandscapeLayout();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "tabOneFragment", tabOneFragment);
getSupportFragmentManager().putFragment(outState, "tabTwoFragment", tabTwoFragment);
}
private void setUpPortraitLayout() {
viewPager = (ViewPager) findViewById(R.id.pager);
// Assign created adapter to viewPager
viewPager.setAdapter(new TabsPagerAdapter(getSupportFragmentManager()));
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
// This method setup all required method for TabLayout with Viewpager
tabLayout.setupWithViewPager(viewPager);
}
private void setUpLandscapeLayout() {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_left, tabOneFragment);
transaction.replace(R.id.fragment_right, tabTwoFragment);
transaction.addToBackStack(null);
transaction.commit();
}
private class TabsPagerAdapter extends FragmentPagerAdapter {
// As we are implementing two tabs
private static final int NUM_ITEMS = 2;
public TabsPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
// For each tab different fragment is returned
public Fragment getItem(int position) {
switch (position) {
case 0:
return tabOneFragment;
case 1:
return tabTwoFragment;
default:
throw new IllegalStateException("Invalid tab index");
}
}
#Override
public int getCount() { return NUM_ITEMS; }
#Override
public CharSequence getPageTitle(int position) { return "Tab " + (position + 1); }
// NOTE: I think you do not really need to override "instantiateItem()", therefore I removed it.
}
}

Android Fragment Always NULL When Accessing From ViewPagerAdapter

The Problem:
In my onCreate() on my main activity, I am trying to set the text value of a TextView in my fragment which is displayed by a viewpager. When I try to get my fragment instance, It always returns null.
Solutions I Tried:
Almost every solution related to this problem on SO gives me the same result(NPE).
My Code is below as well as some explanation...
Home.java Activity (My Main Activity):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Show the home layout
setContentView(R.layout.home);
// Setup the toolbar
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Now setup our tab bar
TabLayout tabLayout = (TabLayout)findViewById(R.id.homeTabs);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
// Setup the view pager
ViewPager viewPager = (ViewPager)findViewById(R.id.viewPager);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
tabLayout.setupWithViewPager(viewPager);
// Start our service controller
Intent startServiceController = new Intent(this, ServiceController.class);
startService(startServiceController);
Fragment viewFragment = pagerAdapter.getRegisteredFragment(viewPager.getCurrentItem());
if(viewFragment == null){
Log.v("Fragment", "NULL");
}
}
After setting up the pageAdapter and viewpager, I try to access the fragment thats being shown. The code for my PagerAdapter is below...
PagerAdapter:
public class PagerAdapter extends SmartFragmentStatePagerAdapter {
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new ParkListFragment();
case 1:
return new MapFragment();
default:
return null;
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
CharSequence title;
switch (position){
case 0:
title = "Spaces Near You";
break;
case 1:
title = "Map";
break;
default:
title = "N/A";
break;
}
return title;
}
}
SmartFragmentStatePagerAdapter:
public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
// Sparse array to keep track of registered fragments in memory
private SparseArray<Fragment> registeredFragments = new SparseArray<>();
public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
// Register the fragment when the item is instantiated
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
// Unregister when the item is inactive
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
// Returns the fragment for the position (if instantiated)
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
I really don't understand what the issue is. I have tried many things. What I don't want to use is this:
String tag="android:switcher:" + viewId + ":" + index;
ParkListFragment.java:
public class ParkListFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.park_list_fragment, container, false);
}
}
ParkList Fragment Layout:
<?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"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/confidenceText"
android:textAlignment="center"
android:textSize="24sp"
android:textColor="#android:color/primary_text_light"
android:padding="10dp"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/activityText"
android:textAlignment="center"
android:textSize="24sp"
android:textColor="#android:color/primary_text_light"
android:padding="10dp"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
Stack Trace: Pastebin
So after hours of trial and error, the only thing that worked for me was this SO post:
ViewPager Fragments are not initiated in onCreate

Viewpager with listview inside

i want to create a viewpager with one layout that contains a listview but i'm always getting this error:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.myapp/com.example.myapp.Join_activity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a
null object reference
The viewpager works fine without the listview, and the listview works fine without the viewpager. I know the problem, i'm using "setContentView" with a different layout where my listview is, but i don't know how to solve it, please help, here is the code:
public class Join_activity extends AppCompatActivity {
ListView lv_zona;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.join_pager);//here is the problem
//my listview is in join3.xml
//ViewPager
viewPager = (ViewPager) findViewById(R.id.viewpaginador);
viewPager.setAdapter(new Join_Adapter(this));
//ListView
lv_zona = (ListView)findViewById(R.id.lv_zona);
lv_zona.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1,new String[]{"A1","B1","C1","D1"}));
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state){}
});
}//end oncreate
}//end class
*
public class Join_Adapter extends PagerAdapter {
private Context mContext;
public Join_Adapter(Context context) {
mContext = context;
}
#Override
public Object instantiateItem(ViewGroup coleccion, int posicion) {
ModelObject modelObject = ModelObject.values()[posicion];
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup mlayout = (ViewGroup) inflater.inflate(modelObject.getLayoutResId(), coleccion, false);
coleccion.addView(mlayout);
return mlayout;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view)
{collection.removeView((View) view);}
#Override
public int getCount()
{return ModelObject.values().length;}
#Override
public boolean isViewFromObject(View view, Object object)
{return view == object;}
#Override
public CharSequence getPageTitle(int position) {
ModelObject customPagerEnum = ModelObject.values()[position];
return mContext.getString(customPagerEnum.getTitleResId());
}
}
My files:
My_files.jpg
My xmls:
***join3.xml - Here is my ListView***
<?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">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lv_zona"
android:choiceMode="singleChoice" />
</LinearLayout> </LinearLayout>
*
***join_pager.xml - my main layout***
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Paginador">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView2" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpaginador"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
You should use fragments for this. You are using a view pager. Now you should display the list inside a fragment that you will load in the activity. This answer shows how to do that. Your fragment xml will contain the listView. And the getItem of the adapter will return the fragment.
The reason of NullPointerException is the list activity is not in the main layout, so, findViewById returns null.
To put a listview in a ViewPager, see: https://stackoverflow.com/a/12535150/189961

Implementing ViewPager into a LinearLayout

What I am trying to do is to have a ViewPager section on my app, where the user can scroll to see the results. I am using Android Studio.
At the moment I am currently displaying the results like so, by outputting the values to out by stringing them together:
Part of Main_Activity.java
class CustomOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
String tempValue = spinner1.getSelectedItem().toString();
float inputValue;
if(text.getText().length() == 0) {
inputValue = Float.parseFloat("10");
text.setText("10");
}
else {
inputValue = Float.parseFloat(text.getText().toString());
}
if ("Fahrenheit".equals(tempValue)) {
out.setText(String.valueOf(ConverterUtil.convertFahrenheitToCelsius(inputValue)) + " & " + String.valueOf(ConverterUtil.convertFahrenheitToKelvin(inputValue)));
type.setText("Celsius + Kelvin");
}
if ("Celsius".equals(tempValue)) {
out.setText(String.valueOf(ConverterUtil.convertCelsiusToFahrenheit(inputValue)) + " & " + String.valueOf(ConverterUtil.convertCelsiusToKelvin(inputValue)));
type.setText("Fahrenheit + Kelvin");
}
if ("Kelvin".equals(tempValue)) {
out.setText(String.valueOf(ConverterUtil.convertKelvinToCelsius(inputValue)) + " & " + String.valueOf(ConverterUtil.convertKelvinToFahrenheit(inputValue)));
type.setText("Celsius + Fahrenheit");
}
}
What I would like to do is to to have each result in a separate view in which the user can scroll, however this is where I get a little lost/confused.
I have implemented my Fragment:
Part of Main_Activity.java
class ScreenSlidePagerActivity extends FragmentActivity
{
private static final int NUM_PAGES = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return new ScreenSlidePageFragment();
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
and in the activity_main.xml layout, I have replaced the out & type fields with a ViewPager:
Part of activity_main.xml
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
When called, it loads this class and displays the information using my result_slider layout:
ScreenSlidePageFragment.java
public class ScreenSlidePageFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.result_slider, container, false);
return rootView;
}
}
result_slider.xml
<com.example.temperatureconverter
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView style="?android:textAppearanceMedium"
android:padding="16dp"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello World" />
</com.example.temperatureconverter>
How can I go about passing the data from my results to a pane in the ViewPager? Using the code below, I don't get any errors, however the app crashes with Error inflating class android.support.v4.view.ViewPager
Try following the answer to this question: How to implement a ViewPager with different Fragments / Layouts
Make sure you include the libraries and merge your MainActivity with the one from the answer.
Then in your layout file for the MainActivity, put your ViewPager
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
Where you would like the content to scroll/go

Categories

Resources