Custom ViewPager rendering problem on some devices:

I developed a kind of rolling mechanism for selecting personnel in the application. This is a custom pager that allows you to display more than one element on the screen at a time (3 in my case) and surrounded by a shadow on both sides.

Here's how it should look and work on devices like the Nexus 5 , Nexus 4 , Galaxy S3 :

enter image description here

But on some devices, such as ( Sony Xperia and various types of Motorola ), the rendering looks bad, here is the result:

enter image description here

Regarding the code, I referred to this @Commonsware blog post :

http://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html

And the third option is there, in the code of which you can find here .

Here is my code:

PagerContainer:

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. if (Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT < 19) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } } @Override protected void 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) { invalidate(); } @Override public void onPageScrollStateChanged(int state) { mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE); } } 

Init element:

  //Size View Pager: //======================================== pagerSize = mContainerSize.getViewPager(); adapter = new MySizePagerAdapter(); pagerSize.setAdapter(adapter); //Necessary or the pager will only have one extra page to show make this at least however many pages you can see pagerSize.setOffscreenPageLimit(adapter.getCount()); //A little space between pages pagerSize.setPageMargin(15); //If hardware acceleration is enabled, you should also remove clipping on the pager for its children. pagerSize.setClipChildren(false); 

More research has led me to realize that this problem has something to do with hardware acceleration or lack on some devices. But disabling it with the code didn't help me either.

Has anyone encountered this problem and know how to fix it?

Thanks in advance.

+7
android view android-viewpager rendering
source share
2 answers

I ended up using another ViewPager implementation that gave me the same result, but the rendering problem was not where it could be seen, this is the code:

  private class MyTypePagerAdapter extends PagerAdapter { @Override public Object instantiateItem(ViewGroup container, int position) { TextView view = new TextView(getActivity()); view.setText(mTempBeverageList.get(position).getName().toUpperCase()); if (!wasTypeChanged && (!isLocaleHebrew && position == 1)) { view.setTypeface(null, Typeface.BOLD); view.setTextSize(19); } else { view.setTextSize(16); } view.setSingleLine(); view.setGravity(Gravity.CENTER); view.setTextColor(getResources().getColor(R.color.cups_black)); view.setBackgroundColor(getResources().getColor(R.color.cups_cyan)); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View)object); } @Override public int getCount() { return mTempBeverageList.size(); } @Override public float getPageWidth(int position) { return (0.33333f); } @Override public boolean isViewFromObject(View view, Object object) { return (view == object); } } 

And the initialization part:

 pagerType= (ViewPager) view.findViewById(R.id.pagerType); pagerType.setAdapter(new MyTypePagerAdapter()); pagerType.setOffscreenPageLimit(6); 
0
source share

I would try setting layerType for the ViewPager and its children to render the software instead of the original layout.

You can also check out this blog post: http://udinic.wordpress.com/2013/09/16/viewpager-and-hardware-acceleration/

+2
source share

All Articles