Put a button on a page from a ViewPager - android

I'm using ViewPager. I want to put a button on each page, but in doing so fills the entire page. I would like to determine the width and height of button but do not know how.
This is my code:
Pager Activity
public class PagerActivity extends Activity {
PagerContainer mContainer;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContainer = (PagerContainer) findViewById(R.id.pager_container);
ViewPager pager = mContainer.getViewPager();
PagerAdapter adapter = new MyPagerAdapter();
pager.setAdapter(adapter);
//Necessary or the pager will only have one extra page to show
// make this at least however many pages you can see
pager.setOffscreenPageLimit(adapter.getCount());
//A little space between pages
pager.setPageMargin(15);
//If hardware acceleration is enabled, you should also remove
// clipping on the pager for its children.
pager.setClipChildren(false);
}
//Nothing special about this adapter, just throwing up colored views for demo
private class MyPagerAdapter extends PagerAdapter {
#Override
public Object instantiateItem(ViewGroup container, int position) {
TextView view = new TextView(PagerActivity.this);
view.setText("Item "+position);
view.setGravity(Gravity.CENTER);
view.setBackgroundColor(Color.argb(255, position * 50, position * 10, position * 50));
view.setTextColor(Color.parseColor("#CA2C68"));
Button buttonView = new Button(PagerActivity.this);
buttonView.setBackgroundResource(R.drawable.button_states_azul);
container.addView(buttonView);
return buttonView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
#Override
public int getCount() {
return 5;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#FF7CB8"
android:id="#+id/linear" >
<View
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="#CA2C68"
android:layout_gravity="bottom"/>
</LinearLayout>
<com.example.slidee.PagerContainer
android:id="#+id/pager_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/linear"
android:layout_alignParentBottom="true"
android:layout_below="#+id/linear"
android:background="#29C5FF" >
<android.support.v4.view.ViewPager
android:layout_width="234dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="#29C5FF" />
</com.example.slidee.PagerContainer>

ViewPager expects the contained view to occupy the whole container.
Use some layout to contain a button:
LinearLayout lay = new LinearLayout(PagerActivity.this);
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
buttonView.setLayoutParams(lp);
lay.addView(buttonView);
container.addView(lay);

an other way to do it is to make a new xml file and inflate it.
<?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">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/viewpager_button"
android:background="#drawable/button_states_azul"/>
</LinearLayout>
and in instantiateItem
LayoutInflater inflater = MainActivity.this.getLayoutInflater();
View pagerView = inflater.inflate(R.layout.viewpager_layout, null);
Button button = (Button) pagerView.findViewById(R.id.viewpager_button);
container.addView(button);

You are creating the button dynamically and hence by default it does a match_parent for width and height.
Add this line:
buttonView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));

This is how i do it, create a xml layout you want to inflate. Add all the view you are intending. Then inside your adapter class, inside instantiateItem override do something like this. remember to adjust your xml views to fit parents width and height as you wish.
#Override
public Object instantiateItem(ViewGroup container, final int position) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.your_view, container, false);
// get reference to your button over here if you have one
Button b = (Button) view.findViewById(R.id.enter_button);
container.addView(view);
return view;
}

Related

NullPointerException for OnClicklistener for ImageView [duplicate]

Can anyone help me to find out what can be the issue with this program.
In the onCreate() method the findViewById() returns null for all ids and this causes a null pointer exception later. I can not figure out why the findViewById() can not find the view. Any suggestions?
This is the main code:
public class MainActivity extends Activity {
ViewPager pager;
MyPagerAdapter adapter;
LinearLayout layout1, layout2, layout3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout1 = (LinearLayout) findViewById(R.id.first_View);
layout2 = (LinearLayout) findViewById(R.id.second_View);
layout3 = (LinearLayout) findViewById(R.id.third_View);
adapter = new MyPagerAdapter();
pager = (ViewPager) findViewById(R.id.main_pager);
pager.setAdapter(adapter);
}
private class MyPagerAdapter extends PagerAdapter
{
#Override
public int getCount() {
return 3;
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
LinearLayout l = null;
if (position == 0 )
{
l = layout1;
}
if (position == 1)
{
l = layout2;
}
if (position == 2)
{
l = layout3;
}
collection.addView(l, position);
return l;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view==object);
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
}
}
And the related XML files:
activity_main layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#a4c639">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_pager"/>
</LinearLayout>
activity_first layout:
<?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:id="#+id/first_View">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
activity_second layout:
<?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:id="#+id/second_View">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
And the activity_third layout:
<?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:id="#+id/third_View">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
findViewById() returns a View if it exists in the layout you provided in setContentView(), otherwise it returns null and that's what happening to you. Note that if you don't setContentView(), and don't have a valid view to findViewById() on, findViewById() will always return null until you call setContentView().
This also means variables in the top-level trigger an NPE, because they're called before onCreate(), and by extension, before setContentView(). See also the activity lifecycle
Example if you setContentView(R.layout.activity_first); and then call findViewById(R.id.first_View); it will return a View which is your layout.
But if you call findViewById(R.id.second_View); before setContentView(), it will return null since there is not a view in your activity_first.xml layout called #+id/second_View.
Emphasis added
For those cases within an Activity class.
Activity.findViewById(int id)
Finds a view that was identified by the id attribute from the XML that was processed in onCreate(Bundle).
Otherwise, such as an Fragment, Adapter, a View from a LayoutInflater, etc.
View.findViewById(int id)
Look for a child view with the given id. If this view has the given id, return this view.
Either case,
Returns
The view if found or null otherwise.
Now, re-check your XML files. Make sure you put the right value into setContentView or inflater.inflate.
In the case of an Activity, call findViewById after setContentView.
Then, make sure there is a View you are looking for with android:id="#+id/..." in that layout. Make sure the + is at #+id, which will add the resource to the R.id values to ensure you can find it from Java.
The views you're trying to get are not defined in your activity_main layout. You need to programmatically inflate the views you're trying to add to the pager.-
#Override
public Object instantiateItem(ViewGroup collection, int position) {
LinearLayout l = null;
if (position == 0) {
l = (LinearLayout) View.inflate(this, R.layout.activity_first, null);
}
if (position == 1) {
l = (LinearLayout) View.inflate(this, R.layout.activity_second, null);
}
if (position == 2) {
l = (LinearLayout) View.inflate(this, R.layout.activity_third, null);
}
collection.addView(l, position);
return l;
}
Sometimes you need clean your project in Eclipse (Project - Clean..).
add those views to the pager adapter before accessing them.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new MyPagerAdapter();
pager = (ViewPager) findViewById(R.id.main_pager);
pager.setAdapter(adapter);
layout1 = (LinearLayout) findViewById(R.id.first_View);
layout2 = (LinearLayout) findViewById(R.id.second_View);
layout3 = (LinearLayout) findViewById(R.id.third_View);
}
in the pager adapter:
public Object instantiateItem(View collection, int position) {
if(position == 0){
View layout = inflater.inflate(R.layout.activity_first, null);
((ViewPager) collection).addView(layout);
return layout;
}
... and so forth.
}
from here you can access them via findViewById.
In my case, it was a stupid mistake on my part. I had written code in the OnCreate method but it was above the setContentView line of code. Once I moved my code below this line the application started working fine.
setContentView(R.layout.activity_main);
What #Warlock said above is right , you should initial LinearLayout layout1, layout2, layout3 by the right way:
LinearLayout layout1 = (LinearLayout) View.inflate(this, R.layout.first_View, null);
LinearLayout layout2 = (LinearLayout) View.inflate(this, R.layout.second_View, null);
LinearLayout layout3 = (LinearLayout) View.inflate(this, R.layout.third, null);
wish my advise help you
I have gotten this error today and it was so simple to clear, that I "facepalmed".
Just try to add the UI element to your layout xml File in your res/layout-port directory!!!
In Android, findViewById(R.id.some_id) works when you are finding view in the layout set.
That is, if you have set a layout say:
setContentView(R.layout.my_layout);
Views can be found only in this layout (my_layout).
In your code layout1, layout2, layout3 all are three different layouts and they are not set to the activity.
The findViewById method must find what is in the layout (which you called in the setContentView)
Use the adaptor, to inflate the layout, and based on the position you can search for the view.
override fun instantiateItem(collection: ViewGroup, position: Int) : ViewGroup {
val inflater = LayoutInflater.from(mContext)
val layout = inflater.inflate(mData[position], collection, false) as ViewGroup
if(position == your_position) {
val nameOfField: TextView = layout.findViewById(R.id.item_id)
}
This problem is also generated when you are having same name of many components in XML file. Even if they are different layout files you should give every element a unique name.
This error occur because you are having a XML element with the same name in another layout file and android studio is trying to access that and showing this error

How to dynamically add image to a viewpager containing imageview?

I have a viewpager in my main_layout. The view pager contains only an ImageView wrapped by RelativeLayout
What i would like to do is when a user click on a button, it will add an image to that particular viewpager.
I found this answer here on stackoverflow (which i think it is relevant to my question), however i am completely lost with that code.
Dynamically Adding View to viewpager
So far this is my code:
MainActivity.Java
private PagerAdapter pAdapter;
private ViewPager photoPager;
...
pAdapter = new GalleryPagerAdapter(getApplicationContext());
photoPager.setAdapter(pAdapter);
GalleryPagerAdapter.java
public class GalleryPagerAdapter extends PagerAdapter{
private final Context context;
LayoutInflater inflater;
private final int[] GalImages = new int[] {
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher
};
public GalleryPagerAdapter(Context context){
this.context=context;
}
#Override
public int getCount() {
return GalImages.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(context);
int padding = 10;
imageView.setPadding(padding, padding, padding, padding);
imageView.setScaleType(ImageView.ScaleType.MATRIX);
imageView.setImageResource(GalImages[position]);
container.addView(imageView, 0);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((ImageView) object);
}
}
This is the view that i would like to add dynamically
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="10dp" >
<ImageView
android:id="#+id/photo_thumb"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#000000"
android:scaleType="fitXY"
android:padding="0dp" />
</RelativeLayout>
And this is my MainActivity where my ViewPager exists
MainActivity.xml
<LinearLayout
android:id="#+id/bannerLayout"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.4"
android:layout_margin="0dip"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/photoPager"
android:layout_width="fill_parent"
android:layout_height="125dp"
android:background="#4F4E4F"/>
</LinearLayout>
So my question is how do i improve the code i am using so that i can dynamically add new image to my ViewPager
ps: On the reference link (which i strongly believe relevant to my question), i am completely lost on this part:
// Create an initial view to display; must be a subclass of FrameLayout.
FrameLayout v0 = (FrameLayout) inflater.inflate (R.layout.one_of_my_page_layouts, null);
pagerAdapter.addView (v0, 0);
What is inflater ?? What should i initialize it to?
I hope someone could direct me. And i am sorry if i sound like asking multiple question here.
Inflater is used to create View object out of your xml layout.
So if your lauout R.layout.one_of_my_page_layouts:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="10dp" >
<ImageView
android:id="#+id/photo_thumb"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#000000"
android:scaleType="fitXY"
android:padding="0dp" />
</RelativeLayout>
Inflater will do something like this(Just an example)
ImageView iv=new ImageView(context);
RelativeLayout rl=new RelativeLayout(context);
rl.add(iv)
return rl;
Just the minimal code but inflater will set all the layout params as well.
So instead of create a view dynamically like you are doing in instantiateItem if you have an xml you can simply inflate it and get an object of Type view.
So you can change instantiateItem to:
public Object instantiateItem(ViewGroup container, int position) {
RelativeLayout v0 = (RelativeLayout ) inflater.inflate (R.layout.one_of_my_page_layouts, null);
ImageView imageView = vo.findViewById(R.id.photo_thumb);
int padding = 10;
imageView.setPadding(padding, padding, padding, padding);
imageView.setScaleType(ImageView.ScaleType.MATRIX);
imageView.setImageResource(GalImages[position]);
container.addView(v0, 0);
return v0;
}

Simulate Android ViewPager Animation with View in front of it

I would like to simulate the animation of a view pager, for changing the background color, but the idea is to have a view (or more) that stays in front of the background at all time (even when switching it).
Any suggestion would be really nice to hear.
Edit: This is an example of what I`m trying to achieve:
http://www.youtube.com/watch?v=mB7GmfMxLvY
There are couple of ways how this can be done. You can create views with different background and then use animations to get the desired effect. However, since you mentioned ViewPager, and if that is what you need.. an easier solution is use a Relative layout and overlay other views on top of a view pager.
Take a look here:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/viewpager"
android:layout_alignParentRight="false"/>
<!-- other views go here -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/ic_launcher"/>
</RelativeLayout>
Then assign views to the view pager with different background colors. (Note: written the code in short time to explain the solution)
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
colors = new ArrayList<Integer>();
colors.add(Color.RED);
colors.add(Color.BLACK);
colors.add(Color.BLUE);
colors.add(Color.GREEN);
colors.add(Color.YELLOW);
mViewPager = (ViewPager)findViewById(R.id.viewpager);
mPageAdapter = new MyPageAdapter();
mViewPager.setAdapter(mPageAdapter);
mPageAdapter.notifyDataSetChanged();
}
private MyPageAdapter mPageAdapter;
private ViewPager mViewPager;
private List<Integer> colors;
class MyPageAdapter extends PagerAdapter {
#Override
public int getCount() {
return colors.size();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
RelativeLayout view = new RelativeLayout(getApplicationContext());
view.setBackgroundColor(colors.get(position));
((ViewPager) mViewPager).addView(view, 0);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object view) {
((ViewPager) mViewPager).removeView((RelativeLayout) view);
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view == ((RelativeLayout) o);
}
}
}
So this way you can achieve all the properties of the view pager (gestures, slide effect etc.) without writing any extra code).

Android: How to implement viewpager and views in single xml file

UPDATED : Can I use the following layout to implement 3 textviews in Viewpager :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="view 1"/>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="view 2"/>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="view 3"/>
</android.support.v4.view.ViewPager>
</LinearLayout>
I want to implement the ViewPager for these 3 views. and i want to have viewpager and those 3 views in single xml file. Each page contains each textview. I have seen some examples but each page was implement using separate xml layout file.
How can I implement the viewpager for these 3 views in a single xml file. If possible please provide me a sample code or example.
You can use a single XML layout nesting the children views.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/page_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:text="PAGE ONE IN"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#fff"
android:textSize="24dp"/>
</LinearLayout>
<LinearLayout
android:id="#+id/page_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:text="PAGE TWO IN"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#fff"
android:textSize="24dp"/>
</LinearLayout>
</android.support.v4.view.ViewPager>
</LinearLayout>
BUT... you need handle this with an adapter also. Here we return the finded view ID without inflate any other layout.
class WizardPagerAdapter extends PagerAdapter {
public Object instantiateItem(View collection, int position) {
int resId = 0;
switch (position) {
case 0:
resId = R.id.page_one;
break;
case 1:
resId = R.id.page_two;
break;
}
return findViewById(resId);
}
#Override
public int getCount() {
return 2;
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
}
// Set the ViewPager adapter
WizardPagerAdapter adapter = new WizardPagerAdapter();
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
My question is... Some Guru here can teach me if is possible that the ViewPager read the children from XML and auto build the pages without use the instantiateItem()?
Update
This answer will show optimised and managed way to set ViewPager pages inside layout.
Step 1
First make two pages Layouts XML layout_page_1.xml and layout_page_2.xml.
Step 2
Now include all pages layout in your parent layout ViewPager.
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/page_one"
layout="#layout/layout_page_1" />
<include
android:id="#+id/page_two"
layout="#layout/layout_page_2" />
</androidx.viewpager.widget.ViewPager>
Step 3
Now from your code, set adapter in simple steps
// find views by id
ViewPager viewPager = findViewById(R.id.viewpager);
CommonPagerAdapter adapter = new CommonPagerAdapter();
// insert page ids
adapter.insertViewId(R.id.page_one);
adapter.insertViewId(R.id.page_two);
// attach adapter to viewpager
viewPager.setAdapter(adapter);
That's All! You need only a common adapter for all ViewPagers.
CommonPagerAdapter.java class
public class CommonPagerAdapter extends PagerAdapter {
private List<Integer> pageIds = new ArrayList<>();
public void insertViewId(#IdRes int pageId) {
pageIds.add(pageId);
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
return container.findViewById(pageIds.get(position));
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
container.removeView((View) object);
}
#Override
public int getCount() {
return pageIds.size();
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object object) {
return view == object;
}
}
Important Note
It is better to use Fragments instead of Views. You should create Fragments and use FragmentStatePagerAdapter to maintain stack, lifecycle and states. You can see #this answer for complete code of using FragmentStatePagerAdapter.
thats impossible .you can do it like these
<?xml version="1.0" encoding="utf-8"?>
<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" />
then create seperate xml file and do it like this.for eg:i am gonna use the xml file name is ios_frag.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:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50sp"/>
</LinearLayout>
Just if anyone faces the same problem, I've solved it with an adapter which extracts the page views from an arbitrary viewgroup that you pass to it.
package com.packagename;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class ViewGroupPagerAdapter extends PagerAdapter {
public ViewGroupPagerAdapter(ViewGroup viewGroup) {
while (viewGroup.getChildCount() > 0) {
views.add(viewGroup.getChildAt(0));
viewGroup.removeViewAt(0);
}
}
private List<View> views = new ArrayList<View>();
#Override
public Object instantiateItem(ViewGroup parent, int position) {
View view = views.get(position);
ViewPager.LayoutParams lp = new ViewPager.LayoutParams();
lp.width = ViewPager.LayoutParams.FILL_PARENT;
lp.height = ViewPager.LayoutParams.FILL_PARENT;
view.setLayoutParams(lp);
parent.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup parent, int position, Object object) {
View view = (View) object;
parent.removeView(view);
}
#Override
public int getCount() {
return views.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
Usage:
ViewPager viewPager=findViewById(...); // Retrieve the view pager
viewPager.setAdapter(new ViewGroupPagerAdapter(findViewById(R.id.id_of_your_view_group_where_you_store_the_pages)));
You can subclass ViewPager and override onInflate.
Moreover, you will get a preview of the first ViewPager page in the Layout Editor.
All views are kept in memory so for performance reasons you should only use this with a small number of pages.
#Override protected void onFinishInflate() {
int childCount = getChildCount();
final List<View> pages = new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
Class<?> clazz = child.getClass();
if (clazz.getAnnotation(DecorView.class) == null) {
pages.add(child);
}
}
for (View page : pages) {
removeView(page);
}
setAdapter(new PagerAdapter() {
#Override public int getCount() {
return pages.size();
}
#Override public Object instantiateItem(ViewGroup container, int position) {
container.addView(pages.get(position));
return position;
}
#Override public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(pages.get((Integer)object));
}
#Override public boolean isViewFromObject(View view, Object object) {
return pages.get((Integer)object) == view;
}
});
super.onFinishInflate();
}
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyPagerAdapter(rootView));
viewPager.setOffscreenPageLimit(3); //or whatever you like
it caches it and shows perfectly.
How can I implement the viewpager for these 3 views in a single xml file.
Sorry, but that is not possible.
add this in your xml layout file
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
create 3 Fragments and add each TextView for every fragment. Then create an adapter that subclassed PagerAdapter
A good example can be found here
Simply : add a ViewPager in your file and put inside your 3 TextView...

Android different widths of layouts in ViewPager

I want to create some scroll view using Horizontal View Pager. Left view must has full screen width, but right only a quarter of width (it will be a vertical panel like in Dolphin browser). It's possible to do that? I changed android:layout_width in right layout, but it didn't work.
My code:
public class TestActivity extends FragmentActivity {
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_view);
MyPagerAdapter adapter = new MyPagerAdapter();
ViewPager pager = (ViewPager) findViewById(R.id.panelPager);
pager.setAdapter(adapter);
pager.setCurrentItem(0);
}
}
main_view.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/panelPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
MyPagerAdapter.java
public class MyPagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return 2;
}
#Override
public Object instantiateItem(final View collection, final int position) {
LayoutInflater inflater =
(LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int resId = 0;
switch (position) {
case 0:
resId = R.layout.left;
break;
case 1:
resId = R.layout.right;
break;
}
View view = inflater.inflate(resId, null);
((ViewPager) collection).addView(view, 0);
return view;
}
#Override
public void destroyItem(final View arg0, final int arg1, final Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
#Override
public boolean isViewFromObject(final View arg0, final Object arg1) {
return arg0 == ((View) arg1);
}
left.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LEFT" />
</LinearLayout>
right.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="50dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/light_blue" >
<TextView
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="RIGHT"/>
</LinearLayout>
Check Murphy's answer on this question. You need to override PagerAdapter's getPageWidth() method on your PagerAdapter class, like this for example:
#Override
public float getPageWidth(int page) {
if(page==0) {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return (float)LEFT_FRAGMENT_PIXEL_WIDTH / size.x;
}
else
return super.getPageWidth(page);
}
Looking at the source for ViewPager, this isn't something it's designed to do; it uses its own width to calculate scroll distances etc, with the clear assumption that all children will have the same width as the ViewPager itself.
For your specific case there may be a hacky workaround, though. You can specify a margin between adjacent pages, and this margin can be negative. This may give the result you want, provided the Z-ordering of the ViewPager's children is appropriate. Give it a try, and see whether it does what you need.
Adrian is exactly right. ViewPager isn't designed to show a portion of the next post as a preview/teaser but it can do it. In my ViewPagerCursorAdapter extends PagerAdapter class I run this:
public Object instantiateItem(View collection, final int position) {
cursor.moveToPosition(position);
View newView = getPageView(cursor, collection);
if (cursor.getCount() > 1) {
((ViewPager)collection).setPageMargin(-overlapMargin);
if (! cursor.isLast()) { newView.setPadding(0, 0, overlapMargin, 0); }
}
((ViewPager) collection).addView(newView);
return newView; //returns the object reference as the tag for identification.
}
You will run into a strange z overlapping issue. The trick is to either apply the background only to ViewPager's background or to apply it to the view inside the newView you just set the padding for. Looks good and works great.

Categories

Resources