Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android PagerAdapter not reporting correct position if click previous item

I have a ViewPager w/ negative margins set to get an effect like this: enter image description here

Now, what I want to happen is that when I click on a view to the left or to the right of the current view. It should select that view and call setCurrentItem() on the ViewPager. This works fine with the view to the right of the current item, but not with the view to the left of the current item. When I click on that view, the position that is reported to me is that of the current view.

Here's some code if it helps. This is from PagerAdapter.instantiateItem() where I'm firing on onClick():

    @Override
    public Object instantiateItem(final ViewGroup container, final int position)
    {
        cardLayout.setTag(profile);
        cardLayout.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                // mOnItemClickListener passed in to adapter on initialization
                mOnItemClickListener.onItemClick(null, view, position, 0);
                // other stuff happens here as well
            }
        });
    }

Entire PagerAdapter class for anyone who is interested:

static class GiveTenPagerAdapter extends PagerAdapter
{
    private final int ANIMATION_DURATION;
    private ListenerOnGiveTakeClick mListenerOnGiveTakeClick;
    private List<GiveTen> mGiveTens;
    private Context mContext;
    private LayoutInflater mInflater;

    private boolean mIsCrossFadeAnimationRunning;
    private int mSquarePhotoSideLength;

    GiveTenPagerAdapter(List<GiveTen> giveTens, Context context,
                        ListenerOnGiveTakeClick listenerOnGiveTakeClick)
    {
        mGiveTens = giveTens;
        mContext = context;
        mListenerOnGiveTakeClick = listenerOnGiveTakeClick;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        ANIMATION_DURATION = mContext.getResources().getInteger(android.R.integer.config_mediumAnimTime);
    }

    List<GiveTen> getGiveTens()
    {
        return this.mGiveTens;
    }

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

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

    @Override
    public Object instantiateItem(final ViewGroup container, final int position)
    {
        Logger.d("position=" + position);

        final GiveTen giveTen = mGiveTens.get(position);
        final UserProfile profile = giveTen.getUserProfile();

        final RelativeLayout cardLayout = (RelativeLayout) mInflater.inflate(R.layout.give_ten_card, null);
        final RelativeLayout profilePicLayout = (RelativeLayout) cardLayout.findViewById(R.id.give_ten_profile_pic_layout);
        final ImageView profileImageView = (ImageView) cardLayout.findViewById(R.id.give_ten_profile_pic);
        final View viewFiller = cardLayout.findViewById(R.id.view_filler);
        final int RADIUS = Math.round(mContext.getResources().getDimension(R.dimen.give_ten_card_corner_radius));

        profileImageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
        {
            @Override
            public boolean onPreDraw()
            {
                profileImageView.getViewTreeObserver().removeOnPreDrawListener(this);

                //kv Using Math.max() to ensure that at least 1 dimension is positive
                //kv in case of some fucked up situation where the measured width and
                //kv height returns 0
                int widthProfileImageView = Math.max(profileImageView.getMeasuredWidth(), 1);
                int heightCardLayout = Math.max(profileImageView.getMeasuredHeight(), 1);

                //kv Somehow we can get into a situation where we in this PreDrawListener and there
                //kv are not give tens, which of course gives us a crash on mGiveTens.get(position)
                //kv If we find ourselves in that case, just show icon_photo_placement_lg
                if (mGiveTens.size() > 0)
                {
                    Picasso picasso = Picasso.with(Bakery.getInstance());
                    picasso.setIndicatorsEnabled(BuildConfig.DEBUG);
                    picasso.load(mGiveTens.get(position).getUserProfile().getProfilePic().getUrl())
                            .noFade()
                            .resize(widthProfileImageView, heightCardLayout)
                            .centerCrop()
                            .transform(new PicassoTransformationRounded(RADIUS, 0))
                            .into(profileImageView);
                }
                else
                {
                    profileImageView.setImageResource(R.drawable.icon_photo_placement_lg);
                }

                return true;
            }
        });

        TextView profilePicGenderCriteriaTextView = (TextView) cardLayout.findViewById(R.id.give_ten_profile_pic_textview_gender_criteria);
        TextView profilePicCityTextView = (TextView) cardLayout.findViewById(R.id.give_ten_profile_pic_textview_city);

        if (profile.getCriteriaGender().equals("m"))
        {
            profilePicGenderCriteriaTextView.setText(R.string.give_ten_text_gender_criteria_male);
        }
        else
        {
            profilePicGenderCriteriaTextView.setText(R.string.give_ten_text_gender_criteria_female);
        }

        String cityText = mContext.getResources().getString(R.string.give_ten_profile_pic_text_city_prefix)
                + " "
                + mGiveTens.get(position).getUserProfile().getCity()
                + ", "
                + mGiveTens.get(position).getUserProfile().getState();

        profilePicCityTextView.setText(cityText);

        container.addView(cardLayout);

        final RelativeLayout giveTenDetailsLayout = getDetailsLayout(cardLayout, giveTen);

        viewFiller.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                Logger.d("view=" + view);

                boolean shouldCrossFade = !mListenerOnGiveTakeClick.onGiveTenClick(position - 1, true);

                if (mIsCrossFadeAnimationRunning == false && position > 0 && shouldCrossFade)
                {
                    crossfadeViews(profilePicLayout, giveTenDetailsLayout);
                    ManagerAnalytics.sendEvent(ManagerAnalytics.EVENT_VISITED_GIVE_TEN_CARD, ManagerAnalytics.ST1_PAGEVIEW);
                }
            }
        });

        View.OnClickListener onClickListener = new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                Logger.d("view=" + view);

                boolean shouldCrossFade = !mListenerOnGiveTakeClick.onGiveTenClick(position, false);

                if (mIsCrossFadeAnimationRunning == false && shouldCrossFade)
                {
                    crossfadeViews(giveTenDetailsLayout, profilePicLayout);
                    ManagerAnalytics.sendEvent(ManagerAnalytics.EVENT_VISITED_GIVE_TEN_CARD, ManagerAnalytics.ST1_PAGEVIEW);
                }
            }
        };

        cardLayout.setOnClickListener(onClickListener);

        ScrollView giveTenCardDetailScrollContainer = (ScrollView) cardLayout.findViewById(R.id.give_ten_card_detail_scroll_container);

        if (giveTenCardDetailScrollContainer != null)
        {
            LinearLayout giveTenDetailsFieldLayout = (LinearLayout) giveTenCardDetailScrollContainer.findViewById(R.id.give_ten_detail_fields_layout);

            giveTenDetailsFieldLayout.setTag(profile);
            giveTenDetailsFieldLayout.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View view)
                {
                    Logger.d("view=" + view);

                    boolean shouldCrossFade = !mListenerOnGiveTakeClick.onGiveTenClick(position, false);

                    if (mIsCrossFadeAnimationRunning == false && shouldCrossFade)
                    {
                        crossfadeViews(profilePicLayout, giveTenDetailsLayout);
                        ManagerAnalytics.sendEvent(ManagerAnalytics.EVENT_VISITED_GIVE_TEN_CARD, ManagerAnalytics.ST1_PAGEVIEW);
                    }
                }
            });
        }
        return cardLayout;
    }

    private void crossfadeViews(final View view1, final View view2)
    {
        final View visibleView, invisibleView;

        if (view1.getVisibility() == View.VISIBLE)
        {
            visibleView = view1;
            invisibleView = view2;
        }
        else
        {
            visibleView = view2;
            invisibleView = view1;
        }

        mIsCrossFadeAnimationRunning = true;
        invisibleView.setAlpha(0.0f);
        invisibleView.setVisibility(View.VISIBLE);

        invisibleView.animate()
                .alpha(1.0f)
                .setDuration(ANIMATION_DURATION)
                .setListener(new AnimatorListenerAdapter()
                {
                    @Override
                    public void onAnimationEnd(Animator animation)
                    {
                        mIsCrossFadeAnimationRunning = false;
                    }
                });

        visibleView.animate()
                .alpha(0.0f)
                .setDuration(ANIMATION_DURATION)
                .setListener(new AnimatorListenerAdapter()
                {
                    @Override
                    public void onAnimationEnd(Animator animation)
                    {
                        visibleView.setVisibility(View.GONE);
                        mIsCrossFadeAnimationRunning = false;
                    }
                });

    }

    public void crossFadeViews(View view)
    {
        final RelativeLayout giveTenDetailLayout = (RelativeLayout) view.findViewById(R.id.give_ten_detail_layout);
        final RelativeLayout profilePicLayout = (RelativeLayout) view.findViewById(R.id.give_ten_profile_pic_layout);
        crossfadeViews(profilePicLayout, giveTenDetailLayout);
    }

    private RelativeLayout getDetailsLayout(View parent, GiveTen giveTen)
    {
        RelativeLayout giveTenDetailsLayout = (RelativeLayout) parent.findViewById(R.id.give_ten_detail_layout);

        UserProfile profile = giveTen.getUserProfile();

        TextView genderCriteriaTextView = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_gender_criteria_textview);

        if (profile.getCriteriaGender().equals("m"))
        {
            genderCriteriaTextView.setText(R.string.give_ten_text_gender_criteria_male);
        }
        else
        {
            genderCriteriaTextView.setText(R.string.give_ten_text_gender_criteria_female);
        }

        TextView cityTextView = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_city_textview);
        cityTextView.setText(profile.getCity() + ", " + giveTen.getUserProfile().getState());

        TextView ageTextView = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_age_textview);
        ageTextView.setText(mContext.getResources().getString(R.string.give_ten_text_age)
                + " "
                + DateUtils.getAgeFromBirthday(profile.getBirthday()));

        TextView heightTextView = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_height_textview);
        heightTextView.setText(mContext.getResources().getString(R.string.give_ten_text_height)
                + " "
                + profile.getHeightFeet()
                + "'"
                + profile.getHeightInches());

        TextView religionTextView = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_religion_textview);
        religionTextView.setText((mContext.getResources().getStringArray(R.array.religion)[Religion.getIndex(profile.getReligionApiParam())]));

        TextView educationTextView0 = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_education_1_textview);
        TextView educationTextView1 = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_education_2_textview);

        List<String> education = profile.getEducation();
        List<Degree> degree = profile.getListDegrees();

        if (education.size() > 0)
        {
            if (degree.size() > 0)
            {
                educationTextView0.setText(education.get(0) + "/" + degree.get(0).toString().toLowerCase());
            }
            else
            {
                educationTextView0.setText(education.get(0));
            }

            if (education.size() > 1)
            {
                if (degree.size() > 1)
                {
                    educationTextView1.setText(education.get(1) + "/" + degree.get(1).toString().toLowerCase());
                }
                else
                {
                    educationTextView1.setText(education.get(1));
                }

                educationTextView1.setVisibility(View.VISIBLE);
            }
        }

        TextView occupation = (TextView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_occupation_textview);
        occupation.setText(profile.getOccupation());

        final List<ImageView> giveTenDetailPics = new ArrayList<ImageView>();
        giveTenDetailPics.add((ImageView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_pic_1));
        giveTenDetailPics.add((ImageView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_pic_2));
        giveTenDetailPics.add((ImageView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_pic_3));
        giveTenDetailPics.add((ImageView) giveTenDetailsLayout.findViewById(R.id.give_ten_detail_pic_4));

        //kv Calculate length of side for photos
        float widthPhotoLayout = ViewUtils.getScreenWidth() -
                2 * mContext.getResources().getDimension(R.dimen.give_ten_layout_margin_side) -
                2 * mContext.getResources().getDimension(R.dimen.give_ten_detail_margin_side) -
                6 * mContext.getResources().getDimension(R.dimen.give_ten_photo_margin_side);

        mSquarePhotoSideLength = (int) (widthPhotoLayout / 4);

        List<Photo> detailPhotos = profile.getPhotos();
        for (int i = 0; i < detailPhotos.size(); i++)
        {
            final ImageView imageView = giveTenDetailPics.get(i);
            final Photo photo = detailPhotos.get(i);

            final String url = photo.getUrlThumbnail();
            Logger.d("about to display " + url + ", length=" + mSquarePhotoSideLength);

            Picasso.with(mContext)
                    .load(url)
                    .noFade()
                    .resize(mSquarePhotoSideLength, mSquarePhotoSideLength)
                    .placeholder(R.drawable.icon_photo_placement_s)
                    .into(imageView, new Callback()
                    {
                        @Override
                        public void onSuccess()
                        {
                            //Logger.e("success on " + url);
                        }

                        @Override
                        public void onError()
                        {
                            Logger.e("error");
                        }
                    });
        }

        return giveTenDetailsLayout;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object)
    {
        container.removeView((View) object);
    }
}
like image 308
Karim Varela Avatar asked Mar 23 '15 20:03

Karim Varela


People also ask

When should I use ViewPager?

ViewPager in Android is a class that allows the user to flip left and right through pages of data. This class provides the functionality to flip pages in app. It is a widget found in the support library. To use it you'll have to put the element inside your XML layout file that'll contain multiple child views.

What is the use of ViewPager in Android?

ViewPager in Android allows the user to flip left and right through pages of data. In our android ViewPager application we'll implement a ViewPager that swipes through three views with different images and texts.

How the ViewPager is implemented?

Implement Swipe Views You can create swipe views using AndroidX's ViewPager widget. To use ViewPager and tabs, you need to add a dependency on ViewPager and on Material Components to your project. To insert child views that represent each page, you need to hook this layout to a PagerAdapter .

What is PagerAdapter?

PagerAdapter supports data set changes. Data set changes must occur on the main thread and must end with a call to notifyDataSetChanged similar to AdapterView adapters derived from android. widget. BaseAdapter . A data set change may involve pages being added, removed, or changing position.


2 Answers

You could intercept touch events and get coordinates from that event.

    if(event.getRawX() < margin && canGoLeft){
goLeft();
}
else if(event.getRawX() > screenWidth - margin && canGoRight) {
goRight();
}
else { 
  // We are not interested in this event, pass it down the food chain
}
like image 163
Bojan Kseneman Avatar answered Oct 08 '22 10:10

Bojan Kseneman


It's not a bug.. you have to use different method for it.

Just try the method above the instantiateItem ,

@Override
public void setPrimaryItem(View container, final int position, Object object)
{}

Here position return correct which you have required..

like image 21
Mayur R. Amipara Avatar answered Oct 08 '22 10:10

Mayur R. Amipara