3

I have used Custom ViewPager which extends Viewpager . I have used gesture detector to do the scroll event.

here is my code,

public class VerticalViewPager extends ViewPager {
    private GestureDetector gestureDetector;
    public boolean isScrollEvent;
    public VerticalViewPager(Context context) {
        super(context);
        init();
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        gestureDetector=new GestureDetector(getContext(),new GestureListener());
        setPageTransformer(true, new VerticalPageTransformer());
        setOverScrollMode(OVER_SCROLL_NEVER);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean res=gestureDetector.onTouchEvent((ev));
        Log.d("event", "interceotontouch      " + res);
        return res;

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean res= gestureDetector.onTouchEvent((ev));
        if((ev.getAction() == MotionEvent.ACTION_CANCEL ||ev.getAction()==MotionEvent.ACTION_UP)) {
            if(isScrollEvent) {
                try {
                    endFakeDrag();
                } catch (Exception e) {}
            }
            return true;
        }
        Log.d("event", "ontouch      "+res);
        return res;
    }

    public void setScrollDuration(int duration) {
        mScroller.setScrollDuration(duration);
    }




    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            isScrollEvent=false;
           Log.d("touch","singletap");
            return false;
        }
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
           Log.d("touch","fling");
            isScrollEvent=false;
            try {
                float diffY = e2.getY() - e1.getY();
                if (diffY > 20) {
                    onSwipeDown();
                    return  false;
                } else if(diffY<-20){
                    onSwipeUp();
                    return  false;
                }
                else
                {
                    endFakeDrag();
                    int id = getCurrentItem();
                    setCurrentItem(id, true);
                }


            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return false;

        }
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
         Log.d("touch", "scroll" + " " + distanceX);
            beginFakeDrag();
            fakeDragBy(-distanceY);
            isScrollEvent=true;
            return true;

        }
    }
    public void onSwipeUp() {
        setCurrentItem(getCurrentItem() + 1);

    }
    public void onSwipeDown() {
        setCurrentItem(getCurrentItem() - 1);

    }
}

And this is my PageTranformer,

public class VerticalPageTransformer implements android.support.v4.view.ViewPager.PageTransformer {
    @Override
    public void transformPage(View view, float position) {
        final float MIN_SCALE = 0.85f;
         final float MIN_ALPHA = 0.5f;

                if (position < -1) {
                    view.setAlpha(0);
                } else if (position <= 0) { // [-1,0]
                    view.setAlpha(1);
                    view.setTranslationX(-1 * view.getWidth() * position);
                    float yPosition = position * view.getHeight();
                    view.setTranslationY(yPosition);
                    view.setScaleX(1);
                    view.setScaleY(1);
                } else if (position <= 1) { // (0,1]
                    view.setAlpha(1 - position);
                    view.setTranslationX(-1 * view.getWidth() * position);
                    float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
                    view.setScaleX(scaleFactor);
                    view.setScaleY(scaleFactor);
                } else {
                    view.setAlpha(0);
                }
    }

}

Everything works fine. But the problem is , When I click something in the current page, onClick() event invoked. But it doesn't update the view. The view gets updated after changing the page.

This is my adapter,

public class MainViewPagerAdapter extends PagerAdapter {

    private Context context;
    private List<NHBean> newslist = new ArrayList<>();
    ImageLoader imageLoader;
    List<String> list = new ArrayList<String>();
    SharedPreferences preferences;
    SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    SimpleDateFormat displayFormat = new SimpleDateFormat("MMM dd, hh:mm a");
    public MainViewPagerAdapter(Context context) {
        this.context = context;
        preferences = context.getSharedPreferences("NewsUpdatePref", Context.MODE_PRIVATE);
        imageLoader = new ImageLoader(context);
        String serialized = preferences.getString("BOOKMARKS", null);
        if (serialized != null)
            list.addAll(Arrays.asList(TextUtils.split(serialized, ",")));

    }

    public void addItems(List<NHBean> newslist) {
        this.newslist.clear();
        this.newslist.addAll(newslist);
        notifyDataSetChanged();
    }

    @Override
    public Object instantiateItem(final ViewGroup collection, int position) {
        LayoutInflater inflater = LayoutInflater.from(context);
        final NHBean nhBean = newslist.get(position);
        Log.d("ImageURL"+position,nhBean.getImageUrl());
        ViewGroup layout;
        layout= (ViewGroup) inflater.inflate(R.layout.page, collection, false);


        TextView text = (TextView) layout.findViewById(R.id.text);
        TextView timeText = (TextView) layout.findViewById(R.id.time_text);
        TextView textHead = (TextView) layout.findViewById(R.id.text_head);
        ImageView shareNews = layout. findViewById(R.id.share_news);
        ImageView firstPage = layout. findViewById(R.id.first_page);
        final ImageView bookmark=layout.findViewById(R.id.bookmark);
        firstPage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MainActivity)context).moveToFirstPage();
            }
        });
        shareNews.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //code for share
                }
            }
        });
        bookmark.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("clicked","yes");
                if (list.contains(nhBean.getDate())) {
                    list.remove(nhBean.getDate());
                    bookmark.setImageResource(R.drawable.bookmark_not_added);
                } else {
                    bookmark.setImageResource(R.drawable.bookmark_added);
                    list.add(nhBean.getDate());
                }
                preferences.edit().putString("BOOKMARKS", TextUtils.join(",", list)).apply();

            }
        });

        try {
            timeText.setText(displayFormat.format(dateTimeFormat.parse(nhBean.getDate())));
        } catch (Exception e) {
        }

       text.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MainActivity) context).setToolBarVisibility();

            }
        });

        if (list.contains(nhBean.getDate())) {
            bookmark.setImageResource(R.drawable.bookmark_added);
        } else {
            bookmark.setImageResource(R.drawable.bookmark_not_added);
        }
        textHead.setText(nhBean.getHeadline());
        text.setText(nhBean.getContent() + "\n");

        textHead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, WebViewActivity.class);
                intent.putExtra("text_head", nhBean.getHeadline());
                intent.putExtra("news_url", nhBean.getNewsUrl());
                context.startActivity(intent);
            }
        });
        collection.addView(layout);
        return layout;
    }

    @Override
    public void destroyItem(ViewGroup collection, int position, Object view) {
        collection.removeView((View)view);
    }

    @Override
    public int getCount() {
        return newslist.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public CharSequence getPageTitle(int position) {

        return null;
    }

    public NHBean getItem(int position) {
        return newslist.get(position);
    }


}

When I click these buttons, the onClick() is invoked. Look at bookmark button onclick, setImageResource() is not done. But surprisingly when I scroll, the button image is changed.

Edit:

My MainActivity code,

    mainViewPager = findViewById(R.id.flip_view);
    mainViewPagerAdapter = new MainViewPagerAdapter(this);
    mainViewPager.setAdapter(mainViewPagerAdapter);
    mainViewPager.setScrollDuration(300);
    mainViewPager.addOnPageChangeListener(new VerticalViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

        @Override
        public void onPageSelected(int position) {

            if (position != 0 || !toolbar.getTitle().toString().equals(getString(R.string.allnews))) {
                swipeRefreshLayout.setEnabled(false);
            } else
                swipeRefreshLayout.setEnabled(true);

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
    updateNews();

And the method code,

public void updateNews() {
    try {
        final ArrayList<NHBean> headlines_1 = DBHelper.getInstance(this).getHeadlines();
        mainViewPagerAdapter.addItems(headlines_1);
        swipeRefreshLayout.setRefreshing(false);
    } catch (Throwable e) {
        e.printStackTrace();
    }

}

And also the start animation for each page gets stuck when the page is selected.

Help me !!! Thanks in advance

Jyoti JK
  • 2,141
  • 1
  • 17
  • 40
  • can u please post the main activity where you have initialized the view pager? – Quick learner May 10 '18 at 11:56
  • @quicklearner please check edited question – Jyoti JK May 11 '18 at 03:49
  • add full code for main activity , i wanted to see ((MainActivity)context).moveToFirstPage(); method , atleast post appropriate code – Quick learner May 11 '18 at 04:49
  • @quicklearner it just setcurrentItem(0); And moving to first page is working fine. Just UI updates not happened – Jyoti JK May 11 '18 at 04:55
  • bookmark.setImageResource(R.drawable.bookmark_not_added); this? – Quick learner May 11 '18 at 05:55
  • @quicklearner yeah , It is not done. But when I scroll, the image is changed – Jyoti JK May 11 '18 at 05:59
  • scroll in recycler view /listview? – Quick learner May 11 '18 at 06:20
  • @quicklearner I am not using any nested scrollviews. I am just using a view with image and buttons. And when I am changing page by scrolling /swiping viewpager, the UI updates done. Let me know if you dont understand – Jyoti JK May 11 '18 at 06:25
  • for that you need to save state of fragment on scroll and restore back to same state , because the oncreate() gets called again every type you scroll to alternate position of fragment in viewpager – Quick learner May 11 '18 at 06:32
  • @quicklearner I didn't use fragment. I am just returning a view from instantiateItem() – Jyoti JK May 11 '18 at 06:40
  • would be really better if u just post enough code :) – Quick learner May 11 '18 at 06:41
  • @quicklearner I added adapter code and main activity code works fine. I am just displaying data . No complicated code in it. – Jyoti JK May 11 '18 at 06:54
  • alright ill check – Quick learner May 11 '18 at 07:21
  • @quicklearner The first page (before scrolling/swiping/fling) changes UI. When i scroll, any of pages can't update. I think the problem is with my gesture detection events – Jyoti JK May 11 '18 at 08:14
  • gesture methods get called or not when u swipe? – Quick learner May 11 '18 at 09:13
  • It gets called . Everything is working except updation – Jyoti JK May 11 '18 at 09:18
  • try using worker thread to update UI and let me know if it helps – Quick learner May 11 '18 at 09:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170836/discussion-between-quick-learner-and-jyoti-jk). – Quick learner May 11 '18 at 09:22
  • Did you tried calling `notifyDataSetChanged()` ? check this: https://stackoverflow.com/questions/7263291/viewpager-pageradapter-not-updating-the-view – Sunil Sunny May 14 '18 at 05:08
  • @sunilsunny I am directly setting image when it is clicked.Why should I call notifyDataSetChanged(). And I tried that link solutions but none of those worked for me – Jyoti JK May 14 '18 at 05:14
  • The view is changing while scrolling right? So the issue in your case is somehow view not getting refreshed. So may be you can try calling notifyDataSetChanged() and manually refresh the view. – Sunil Sunny May 14 '18 at 05:21
  • @sunilsunny I accept your point but even the animation also not working. When the page is changed, the new page is displayed with animation(2 sec) . But it is also happening on scroll. Also I am not getting ripple effect on button click. I think the view is blocked from changing anything – Jyoti JK May 14 '18 at 05:26

3 Answers3

0

Try to call notifyDataSetChanged() after onClick() invoked.

Vlad
  • 3,465
  • 1
  • 31
  • 24
0

Override getItemPosition in your PagerAdapter like this:

public int getItemPosition(Object object) {
    return POSITION_NONE;
}

This way, when you call notifyDataSetChanged(), the view pager will remove all views and reload them all. As so the reload effect is obtained.

Koustuv Ganguly
  • 897
  • 7
  • 21
  • notifyDataSetChanged() is costly.I have more that 100 or 200 pages . so it will cause performance issue. My problem is "View is blocked from updation/changes" . please check question clearly. And my code works api>23. – Jyoti JK May 14 '18 at 06:18
  • Try to use FragmentStatePagerAdapter. – Koustuv Ganguly May 14 '18 at 06:25
  • I tried it. But it doesn't change anything. I think the problem is with gesturedetector or ontouchevent() in Vertical Viewpager – Jyoti JK May 14 '18 at 07:18
  • As it is related to api version may be `Class> viewpager = ViewPager.class; Field scroller = viewpager.getDeclaredField("mScroller"); scroller.setAccessible(true);` this is creating problem! – Koustuv Ganguly May 14 '18 at 07:25
  • I tried commenting those lines and tried without gesturedetector. Nothing helps – Jyoti JK May 14 '18 at 07:27
  • Then debug in your `ontouchevent()`. You may find the issue there. – Koustuv Ganguly May 14 '18 at 07:29
  • I found the issue.please check my question now. If I didn't set pagetranformer, it works fine – Jyoti JK May 15 '18 at 05:56
0

The problem is not with the code,

I have used android:hardwareAccelerated="false" in Manifest. After lots of research, I found this.

I just changed,

android:hardwareAccelerated="true"

which solved my problem.

Jyoti JK
  • 2,141
  • 1
  • 17
  • 40