Does the ViewPager have to be the only object present inside the activity layout?
I'm trying to implement something like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/reader_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/page_viewer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Gallery
android:id="#+id/miniatures_gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content" /></LinearLayout>
Where should I have a big pager scrolling in the top (and I have it) and a smaller gallery scrolling under that.
This shows me only the pager and not the gallery.
Any suggestion?
The ViewPager does not support wrap_content as it (usually) never have all its children loaded at the same time, and can therefore not get an appropriate size (the option would be to have a pager that changes size every time you have switched page).
You can however set a precise dimension (e.g. 150dp) and match_parent works as well.
You can also modify the dimensions dynamically from your code by changing the height-attribute in its LayoutParams.
Assign layout weight to view pager as 1 & height = 0dp instead of wrap_content
<android.support.v4.view.ViewPager
android:id="#+id/page_viewer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
I solved the problem with a couple of hacks. Here is what it involves:
First, I needed a layout that would ignore ViewPager's height limit. Used it as a parent layout for ViewPager items.
public class TallLinearLayout extends LinearLayout {
public TallLinearLayout(Context context) {
super(context);
}
public TallLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TallLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
}
}
I then wrote the logic for resizing ViewPager:
private class ViewPagerContentWrapper implements OnGlobalLayoutListener {
private ViewPager mViewPager;
public ViewPagerContentWrapper(ViewPager viewPager) {
mViewPager = viewPager;
}
#Override
public void onGlobalLayout() {
int position = mViewPager.getCurrentItem();
check(position);
check(position + 1);
}
private void check(int position) {
ViewGroup vg = (ViewGroup) mViewPager.getChildAt(position);
View v = vg == null ? null : vg.getChildAt(0);
if (v != null) {
int height = v.getHeight();
if (height > mViewPager.getHeight()) {
resize(height);
}
}
}
private void resize(int height) {
mViewPager.setLayoutParams(
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
height
)
);
}
}
Which I registered as global layout listener:
viewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewPagerContentWrapper(viewPager));
Related
I build customView extending LinearLayout and having simple 3 childrens(2 TextView and ImageView). I create this view dynamically in code and adding it to parent LinearLayout. This view has background, so I can easily spot on the screen, that it is inflated correctly in its place, but any of child is not visible. I checked LayoutInspector and it shows that everything is setted correctly(text values to TextViews and picture to ImageView), but somehow when I try to locate them on inspector they are shown as little dot over my customView:
My CustomView is called DayTileView and this is square with gray background. As you can see on inspector on the left childrens are filled with content. Layout of View:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<merge>
<TextView
android:id="#+id/day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#android:color/white"
/>
<TextView
android:id="#+id/dayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#android:color/white"
/>
<ImageView
android:id="#+id/padlock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_padlock"
/>
</merge>
</layout>
And its code:
public class DayTileView extends LinearLayout {
private DayTileBinding mBinding;
public DayTileView(Context context) {
super(context);
init();
}
public DayTileView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public DayTileView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mBinding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.day_tile, this, true);
setOrientation(VERTICAL);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
setMeasuredDimension(width, width);
}
public void setDay(int day, int month, int year) {
DateTime settedDay = new DateTime().withYear(year).withMonthOfYear(month).withDayOfMonth(day);
mBinding.day.setText(String.valueOf(day));
String dayName = settedDay.dayOfWeek().getAsText();
mBinding.dayName.setText(dayName);
boolean isWeekend = settedDay.dayOfWeek().get() == 6 || settedDay.dayOfWeek().get() == 7;
setBackgroundColor(ContextCompat.getColor(getContext(), isWeekend ? R.color.weekend_bg : R.color.weekday_bg));
}
}
Its use in another CustomView which is also LinearLayout but wiht horizontal orientation (PlannedDayView on inspector):
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<merge>
<*.customViews.DayTileView
android:id="#+id/dayTile"
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="#+id/container"
android:orientation="vertical"
android:layout_weight="1.2"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
</merge>
</layout>
Has anyone any idea what could be casuing this (childs out of view)? When I replace merge for LinearLayout with vertical orientation and same background everything in Design mode of layout is visible correctly, so it should work.
EDIT:
I found out, that if I set during View initalization Padding Top to 10px then dot is moving down. So it looks like from some reasons Android didn't made to inflate correctly TextViews and ImageView
I found out what was the problem:
I overrided onMeasure and didn't measure child Views. Earlier I was using such code to make square View not square ViewGroup.
Corrected code:
final int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
setMeasuredDimension(width, width);
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
After setting correct width and height for View I must measure whole view with new MeasureSpec
How do I keep gridView from needing to scroll by auto adjusting it's height? I would like all items, no matter how many items I add to the gridView to remain on screen without scrolling. Is this possible?
Here is my UI so far.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg"
android:orientation="vertical">
<GridView
android:id="#+id/gv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tv_header"
android:fadingEdge="none"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center"
android:listSelector="#00000000"
android:numColumns="auto_fit"
android:stretchMode="columnWidth" />
</LinearLayout>
I did try adding a weightSum to the root and weight to gridView but it still requires scrolling.
Update: I also tried using a custom gridview. This did not work, but here is my attempt anyway.
public class CustomGridView extends GridView {
public CustomGridView(Context context) {
super(context);
}
public CustomGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST));
getLayoutParams().height = getMeasuredHeight();
}
}
Thanks in advance!
I have found answer to this. You can set the height of each item in the adapter by using
view.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, resizeValue));
resizeValue is the size that you want to adjust your rows to. To get resizeValue you can pass to the adapter mResizeValue based on the calculations relative to your device screen size. Something like
resizevalue = this.getResources().getDisplayMetrics().heightPixels / (NUM_COLS);
I figured out some other ways of calculating the height of each row based on screen size and then doing something similar, however, this requires that you do these calculations after you set your adapter and then update the changes to the adapter. It seems less efficient but I will share that methodology as well.
private void resizeGridView(GridView gridView, int items, int columns) {
ViewGroup.LayoutParams params = gridView.getLayoutParams();
int oneRowHeight = gridView.getHeight();
int rows = (int) (items / columns);
params.height = oneRowHeight * rows;
gridView.setLayoutParams(params);
}
Then after you set your adapter use
gridView.getViewTreeObserver().addOnGlobalLayoutListener(new
ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (!gridViewResized) {
gridViewResized = true;
resizeGridView(gridView, numItems, numColumns);
}
}
});
How do I add a hint on the top of a listView like "Pull down to refresh" which is contained in a swipeRefreshLayout from android.support.v4.
The pull down to refresh works but I want to add a text whenever the user pulls the listview slightly down.
EDIT 10/21/2014
If you update the support-v4 to the latest version (at least 21.0.0) you can use the built-in loading indicator!
I just came up with a simple, yet effective, solution.
The idea is to add a custom ViewGroup that grows its height when the SwipeRefreshLayout child gets pulled down. In this ViewGroup you will put everything you need for your hint (TextViews, ImageViews, ...).
I chose to extend a RelativeLayout because it makes easier to position your "hint" elements.
1) Create a custom widget as follows:
public class SwipeRefreshHintLayout extends RelativeLayout {
public SwipeRefreshHintLayout(Context context) {
super(context);
}
public SwipeRefreshHintLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeRefreshHintLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setSwipeLayoutTarget(final SwipeRefreshLayout swipeRefreshLayout) {
final View swipeTarget = swipeRefreshLayout.getChildAt(0);
if (swipeTarget == null) {
return;
}
swipeTarget.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
private Rect oldBounds = new Rect(), newBounds = new Rect();
#Override
public boolean onPreDraw() {
newBounds.set(swipeTarget.getLeft(), swipeRefreshLayout.getTop(), swipeTarget.getRight(), swipeTarget.getTop());
if (!oldBounds.equals(newBounds)){
getLayoutParams().height = newBounds.height();
requestLayout();
oldBounds.set(newBounds);
}
return true;
}
});
}
}
2) In your Fragment or Activity layout use this custom widget.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.widget.SwipeRefreshHintLayout
android:id="#+id/swipe_hint"
android:layout_width="match_parent"
android:layout_height="0dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="#string/label_swipe_to_refresh"/>
<!-- Any other view positioned using RelativeLayout rules -->
</com.example.widget.SwipeRefreshHintLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
3) Then, in your Activity onCreate() or in your Fragment onCreateView(), put those lines:
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeRefreshHintLayout = (SwipeRefreshHintLayout) rootView.findViewById(R.id.swipe_hint);
mSwipeRefreshHintLayout.setSwipeLayoutTarget(mSwipeRefreshLayout);
Done!
My GridView contains columns of fixed width, with fixed horizontal spacing. If there are not enough columns to fill the screen horziontally, I would like my GridView's width to wrap to its contents, and to center vertical in the screen.
However, regardless of the number of columns I use, the GridView's width grows to fill the screen. The attached image shows this, where the green GridView fills the screen horizontally, despite having only 3 columns and its width being set to "wrap_content".
public class Temp extends Activity
{
private GridView grid;
private int columnWidth = 80;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
View view = getLayoutInflater().inflate(R.layout.gridview, null);
grid = (GridView) view.findViewById(R.id.grid);
grid.setColumnWidth(columnWidth);
grid.setAdapter(new GridAdapter());
setContentView(view);
}
class GridAdapter extends BaseAdapter
{
public GridAdapter()
{
}
public int getCount()
{
return 3;
}
public Object getItem(int position)
{
return null;
}
public long getItemId(int position)
{
return position;
}
public View getView (int position, View convertView, ViewGroup parent)
{
View ret;
if (convertView == null)
{
ret = new ImageView(Temp.this);
ret.setLayoutParams(new GridView.LayoutParams(columnWidth, 100));
ret.setBackgroundColor(Color.WHITE);
}
else
{
ret= convertView;
}
return ret;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#FF0000"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="#+id/grid"
android:background="#00FF00"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="auto_fit"
android:verticalSpacing="2dip"
android:horizontalSpacing="2dip"
android:stretchMode="columnWidth"
android:gravity="center">
</GridView>
</RelativeLayout>
GridView is extremely annoying with this kind of stuff to say the least. In your case, the issue is that saying auto_fit is essentially telling GridView to always fit it horizontally unfortunately. What you could try is to center the individual ImageViews in the row. But then this requires you to change how you have it set up. Rather than have the columns auto fit, just have 1 item per row, but inflate a LinearLayout that has the orientation as horizontal. Then center the Linear Layout with the ImageViews also in it in each row. Hopefully that provides some ideas.
Simply add two empty views at left and right of GridView with weight = 1 and assign 0.5 weight to GridView. Eg.
<LinearLayout
android:layout_width="fill_parent"
android:gravity="center"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<GridView
android:id="#+id/myGridView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="2"
android:scrollbars="none"
android:verticalSpacing="10dp" >
</GridView>
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
The layout suggested above did not work for me.
In the end I found it easiest to achieve the results you want by programatically setting the width and X location of the grid -- using the setX(float) method to center the grid.
I know there is an old question, but this is the answer:
public class GridViewEx extends GridView {
//private int mRequestedNumColumns = 0;
public GridViewEx(Context context) {
super(context);
}
public GridViewEx(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridViewEx(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int numcol=getNumColumns();
int numitems=getAdapter().getCount();
if(numitems<numcol){
int width = (numitems * getColumnWidth())
+ ((numitems -1) * getHorizontalSpacing())
+ getListPaddingLeft() + getListPaddingRight();
setMeasuredDimension(width, getMeasuredHeight());
}
}
}
And when you add or delete elements from your adapter you have to call:
adapter.notifyDataSetChanged();
gridView.invalidate()
After trying out the Gallery and Horizontal Scroll View, I found that the View Pager does what I need but with one minor thing missing. Can the View Pager have multiple views per page?
I know that View Pager shows only 1 view/page per swipe. I was wondering if I can limit my views width so my 2nd view following it will show?
For example: I have 3 views and I want the screen to show view 1 and part of view 2 so the user knows there is more content so they can swipe to view 2.
|view 1|view 2|view 3|
|screen |
I discovered that a perhaps even simpler solution through specifying a negative margin for the ViewPager. I've created the MultiViewPager project on GitHub, which you may want to take a look at:
https://github.com/Pixplicity/MultiViewPager
Although MultiViewPager expects a child view for specifying the dimension, the principle revolves around setting the page margin:
ViewPager.setPageMargin(
getResources().getDimensionPixelOffset(R.dimen.viewpager_margin));
I then specified this dimension in my dimens.xml:
<dimen name="viewpager_margin">-64dp</dimen>
To compensate for overlapping pages, each page's content view has the opposite margin:
android:layout_marginLeft="#dimen/viewpager_margin_fix"
android:layout_marginRight="#dimen/viewpager_margin_fix"
Again in dimens.xml:
<dimen name="viewpager_margin_fix">32dp</dimen>
(Note that the viewpager_margin_fix dimension is half that of the absolute viewpager_margin dimension.)
We implemented this in the Dutch newspaper app De Telegraaf Krant:
Mark Murphy has an interesting blog post addressing precisely this problem. Although I ended up using my own solution in this thread, it's worthwhile looking at Dave Smith's code, which Mark references in the blog post:
https://gist.github.com/8cbe094bb7a783e37ad1/
Warning! Before you take this approach, beware of some very serious issues with this approach, mentioned both at the end of this post and in the comments below.
You'll end up with this:
It effectively works by wrapping a ViewPager into a subclass of FrameLayout, setting it to a specific size, and calling setClipChildren(false). This inhibits Android from clipping the views that exceed beyond the boundaries of the ViewPager, and visually accomplishes what you want.
In XML, it's very simple:
<com.example.pagercontainer.PagerContainer
android:id="#+id/pager_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#CCC">
<android.support.v4.view.ViewPager
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal" />
</com.example.pagercontainer.PagerContainer>
Add in a little code for handling touch events from outside of the ViewPager and invalidating the display when scrolling, and you're done.
That being said, and while this works great in general, I did notice that there is an edge-case that isn't solved with this fairly simple construction: when calling setCurrentPage() on the ViewPager. The only way I could find to resolve this was by subclassing ViewPager itself and having its invalidate() function also invalidate the PagerContainer.
It is possible to show more than one page on the same screen.
One of the ways is by overriding the getPageWidth() method in the PAgerAdapter. getPageWidth() returns a float number between 0 and 1 indicating how much width of the Viewpager should the page occupy. By default it is set to 1. So, you can change this to the width you wish.
You can read more about this here & github project.
This is how I got it:
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="center"
android:layout_marginBottom="8dp"
android:clipToPadding="false"
android:gravity="center"
android:paddingLeft="36dp"
android:paddingRight="36dp"/>
and in activity,i use this :
markPager.setPageMargin(64);
hope it helps!
I had the same problem with the only difference that i needed to show 3 pages at once (previous, current and next pages). After a really long research for the best solution i think i found it.
The solution is a mix of few of the answers here:
As #Paul Lammertsma's answer pointed out - Dave Smith's code in Mark Murphy's blog is the basis for the solution. The only problem for me was that the ViewPager was only on the top part of the screen due to the size they give it in the xml file:
android:layout_width="150dp"
android:layout_height="100dp"
Which wasn't good for my purpose since i was looking for something that will spread all over the screen. So i changed it to wrap the content as you can see here:
<com.example.nutrino_assignment.PagerContainer
android:id="#+id/pager_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#CCC">
<android.support.v4.view.ViewPager
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</com.example.nutrino_assignment.PagerContainer>
Now I lost all the effect of what the tutorial was trying to do. Using #andro's answer i was able to show more then 1 page at a time: exactly 2! The current and the next.
Did so by overriding as follow:
#Override
public float getPageWidth(int position) {
return(0.9f);
}
That was almost what i needed... (even though i think its enough for what you were asking), but for others who might need something like what i was needed:
For the last part of the solution i used the idea in this answer, again by #Paul Lammertsma.
In Dave Smith's code you will find in the onCreate method this line:
//A little space between pages
pager.setPageMargin(15);
which i replaced with:
//A little space between pages
pager.setPageMargin(-64);
now on the first page looks:
|view 1|view 2|view 3|
|screen |
while on the 2nd it looks like:
|view 1|view 2|view 3|
|screen |
Hope it will help someone! I wasted like 2 days on it...
Good luck.
viewPager.setPageMargin(-18);// adjust accordingly ,-means less gap
in imageadapter
private class ImagePagerAdapter2 extends PagerAdapter {
private int[] mImages = new int[] {
R.drawable.add1,
R.drawable.add3,
R.drawable.add4,
R.drawable.add2,
};
#Override
public float getPageWidth(int position) {
return .3f;
}
adjust return value...lesser means more image......0.3 means atleast 3 images at a time.
LayoutParams lp = new LayoutParams(width,height);
viewpager.setLayoutParams(lp);
In xml file using this code(Main Activity)
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="130dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="vertical"
android:weightSum="1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="130dp">
<com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer
android:id="#+id/pager_container"
android:layout_width="match_parent"
android:layout_height="fill_parent">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="100dip"
android:layout_height="100dip"/>
</com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer>
</RelativeLayout>
</LinearLayout>
Main activity xml file add this code
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="130dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="vertical"
android:weightSum="1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="130dp">
<com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer
android:id="#+id/pager_container"
android:layout_width="match_parent"
android:layout_height="fill_parent">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="100dip"
android:layout_height="100dip"/>
</com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer>
</RelativeLayout>
</LinearLayout>
Main Activity code
public class MainActivity extends Activity{
final Integer[] XMEN2= {R.mipmap.bookticket,R.mipmap.safty,R.mipmap.privacy};
private ArrayList<Integer> XMENArray2 = new ArrayList<Integer>();
PagerContainer mContainer;
int currentPage2 = 0;
private static int NUM_PAGES2 = 0;
ViewPager mPager2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initData2();}
private void initViews() {
mPager2 = (ViewPager)findViewById(R.id.viewpager);
mContainer = (PagerContainer)findViewById(R.id.pager_container);
mPager2.setOffscreenPageLimit(5);
mPager2.setPageMargin(15);
mPager2.setClipChildren(false);
}
private void initData2() {
for(int i=0;i<XMEN2.length;i++)
XMENArray2.add(XMEN2[i]);
mPager2.setAdapter(new Sliding_Adaptertwo(getActivity(),XMENArray2));
NUM_PAGES2 =XMEN2.length;
final Handler handler = new Handler();
final Runnable Update = new Runnable() {
public void run() {
if (currentPage2 == NUM_PAGES2) {
currentPage2= 0;
}mPager2.setCurrentItem(currentPage2++, true);
}
};
Timer swipeTimer = new Timer();
swipeTimer.schedule(new TimerTask() {
#Override
public void run() {
handler.post(Update);
}
}, 3000, 3000);
}
}
Pager View pagercontainer class
import android.content.Context;
import android.graphics.Point;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
public class PagerContainer extends FrameLayout implements ViewPager.OnPageChangeListener {
private ViewPager mPager;
boolean mNeedsRedraw = false;
public PagerContainer(Context context) {
super(context);
init();
}
public PagerContainer(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PagerContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
//Disable clipping of children so non-selected pages are visible
setClipChildren(false);
//Child clipping doesn't work with hardware acceleration in Android 3.x/4.x
//You need to set this value here if using hardware acceleration in an
// application targeted at these releases.
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
try {
mPager = (ViewPager) getChildAt(0);
mPager.setOnPageChangeListener(this);
} catch (Exception e) {
throw new IllegalStateException("The root child of PagerContainer must be a ViewPager");
}
}
public ViewPager getViewPager() {
return mPager;
}
private Point mCenter = new Point();
private Point mInitialTouch = new Point();
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCenter.x = w / 2;
mCenter.y = h / 2;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
//We capture any touches not already handled by the ViewPager
// to implement scrolling from a touch outside the pager bounds.
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialTouch.x = (int)ev.getX();
mInitialTouch.y = (int)ev.getY();
default:
ev.offsetLocation(mCenter.x - mInitialTouch.x, mCenter.y - mInitialTouch.y);
break;
}
return mPager.dispatchTouchEvent(ev);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Force the container to redraw on scrolling.
//Without this the outer pages render initially and then stay static
if (mNeedsRedraw) invalidate();
}
#Override
public void onPageSelected(int position) { }
#Override
public void onPageScrollStateChanged(int state) {
mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE);
}
}
and its Adapter
public class Sliding_Adaptertwo extends PagerAdapter {
private ArrayList<Integer> IMAGES;
private LayoutInflater inflater;
private Context context;
public Sliding_Adaptertwo(Context context, ArrayList<Integer> IMAGES) {
this.context = context;
this.IMAGES=IMAGES;
inflater = LayoutInflater.from(context);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public int getCount() {
return IMAGES.size();
}
#Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = inflater.inflate(R.layout.sliding_layout, view, false);
assert imageLayout != null;
final ImageView imageView = (ImageView) imageLayout
.findViewById(R.id.image);
imageView.setImageResource(IMAGES.get(position));
view.addView(imageLayout, 0);
return imageLayout;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
#Override
public Parcelable saveState() {
return null;
}
}
xml file of adapter class
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
>
<ImageView
android:id="#+id/image"
android:layout_width="90dp"
android:layout_height="90dp"
android:adjustViewBounds="true"
android:layout_gravity="center"
android:scaleType="fitXY"
android:src="#drawable/ad1"
/>
</FrameLayout>
it works fine