একটি স্ক্রোলভিউয়ের ভিতরে ভিউপেজারটি সংশোধন করে না


88

আমার একটি 'পৃষ্ঠা' রয়েছে যার এতে বেশ কয়েকটি উপাদান রয়েছে এবং কে বিষয়বস্তু ডিভাইসের উচ্চতার চেয়ে দীর্ঘ। ঠিক আছে, কেবলমাত্র সমস্ত লেআউট (পুরো পৃষ্ঠা) এ এর ​​ভিতরে রাখুন ScrollView, কোনও সমস্যা নেই।

উপাদানগুলির মধ্যে একটি হ'ল ক ViewPager। এটি সঠিকভাবে রেন্ডার করে, তবে একটি সোয়াইপ / ফ্লিংয়ের প্রতিক্রিয়া সঠিকভাবে সম্পাদন করছে না, এটি চটজলদি এবং সর্বদা কাজ করে না। এটি 'এর সাথে বিভ্রান্ত' হয়ে উঠছে বলে মনে হচ্ছে ScrollView, সুতরাং আপনি যখন সঠিক অনুভূমিক লাইনে ঝাঁকুনিতে পড়েন তখন কেবল 100% কাজ করে।

আমি যদি অপসারণ করি ScrollViewতবে ভিউপ্যাজার পুরোপুরি সাড়া দেয়।

আমি প্রায় অনুসন্ধান করেছি এবং এটি একটি পরিচিত ত্রুটি হিসাবে খুঁজে পাইনি। অন্য কেউ এই অভিজ্ঞতা হয়েছে?

  • প্ল্যাটফর্ম সংস্করণ: 1.6
  • সুসংগত লাইব্রেরি v4।
  • ডিভাইস: এইচটিসি অবিশ্বাস্য এস

নীচে আপনার সাথে পরীক্ষা করার জন্য কয়েকটি উদাহরণ কোড দেওয়া হয়েছে, ScrollViewএটি সঠিকভাবে কাজ করতে দেখতে মন্তব্য করুন ।

ক্রিয়াকলাপ:

package com.ss.activities;

import com.ss.R;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.TextView;

public class PagerInsideScollViewActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ViewPager vp = (ViewPager) findViewById(R.id.viewpager);
        vp.setAdapter(new MyPagerAdapter(this));
    }
}

class MyPagerAdapter extends PagerAdapter {

    private Context ctx;

    public MyPagerAdapter(Context context) {
        ctx = context;
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public Object instantiateItem(View collection, int position) {

        TextView tv =  new TextView(ctx);
        tv.setTextSize(50);
        tv.setTextColor(Color.WHITE);
        tv.setText("SMILE DUDE, SMILE DUDE, SMILE DUDE, SMILE DUDE, SMILE DUDE, " +
                "SMILE DUDE, SMILE DUDE, SMILE DUDE, SMILE DUDE, SMILE DUDE, " +
                "SMILE DUDE, SMILE DUDE, SMILE DUDE, SMILE DUDE, SMILE DUDE, " +
                "SMILE DUDE, SMILE DUDE, SMILE DUDE");

        ((ViewPager) collection).addView(tv);

        return tv;

    }

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

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

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
    }

    @Override
    public void startUpdate(View arg0) {
    }

    @Override
    public void finishUpdate(View arg0) {
    }
}

বিন্যাস:

<?xml version="1.0" encoding="utf-8"?>
    <ScrollView
         xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" >

            <android.support.v4.view.ViewPager
                android:id="@+id/viewpager"
                android:layout_width="fill_parent"
                android:layout_height="300dp" />

        </LinearLayout>

    </ScrollView>

এখানে উত্তরটি দেখুন: স্ট্যাকওভারফ্লো
in-

দয়া করে এই লিঙ্কটিতে আমার উত্তরটি দেখান: স্ট্যাকওভারফ্লো.com
জিজ্ঞাসা

উত্তর:


60

আমারও একই সমস্যা ছিল। আমার সমাধানটি requestDisallowInterceptTouchEventযখন কল করা ছিল তখন ভিউপ্যাজারের স্ক্রোলটি শুরু হয়েছিল।

আমার কোডটি এখানে:

pager.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.getParent().requestDisallowInterceptTouchEvent(true);
        return false;
    }
});

pager.setOnPageChangeListener(new SimpleOnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        pager.getParent().requestDisallowInterceptTouchEvent(true);
    }
});

4
এটা কাজ এক ধরনের। আমি স্ক্রোল ভিউটি উল্লম্বভাবে যেতে চাই এমনকি যদি ভিউ পেজারে স্পর্শ শুরু হয় তবে
সরানোটি

4
অন ​​টুচ এবং অন পেজস্ক্রোলড উভয় ক্ষেত্রেই ডিজাললোইন্টারসেপ্ট টাচ এভেন্টের অনুরোধ করা দরকার বা এটি কি কেবল ওভারকিল? আমরা কী কেবলমাত্র পেজস্ক্রোলস্টেটচ্যাঞ্জডে অনুরোধডিশাললোইন্টারসেপ্ট টাচ এভেন্টে সরিয়ে একই ফলাফল পেতে পারি?
ক্রেগারস

4
আমারও একই সমস্যা আছে এবং এই সেরা সমাধানটি খুঁজে পেয়েছি, আশা করি আপনার জন্য এই কাজটি রয়েছে। bitbucket.org/NxAlex/swines-navication-demo/src/…
জিতেন্দ্র নাথ

আমি কীভাবে অন ক্লিকের ইভেন্টটিকে ওভাররাইড করতে পারি? এটি টাচ নিয়ে বিরোধ করে?
কিডো

4
পেজার এবং এমপেজারটি এখানে কী আমাকে ইনপুট দেওয়ার দরকার?
সুজিথরাও

30

আরও পাঠ্য থেকে জানা গেছে যে স্ক্রোলিং উপাদানগুলির ভিতরে স্ক্রোলিং উপাদানগুলির সাথে সমস্যা রয়েছে।

একটি সমাধান হ'ল আমার স্ক্রোলযোগ্য উপাদানটির ক্ষেত্রে স্ক্রোলভিউয়ের উল্লম্ব স্ক্রোলিংটি 'অক্ষম' করা, আমার ক্ষেত্রে একটি ভিউপেজার।

এই সমাধানের কোডটি এখানে বিস্তারিত (এবং এটি কেবল উজ্জ্বল!)


এই পৃষ্ঠায় কোন সমাধানটি উল্লেখ করা উচিত?
হর্ষ এমভি

4
অনুরোধডিসালোলোইন্টারসেপ্ট টাচ ইভেন্টটি আপনি যা খুঁজছেন তা।
ইয়াহিয়া

4
আমারও একই সমস্যা আছে এবং এই সেরা সমাধানটি খুঁজে পেয়েছি, আশা করি আপনার জন্য এই কাজটি রয়েছে। bitbucket.org/NxAlex/swines-navication-demo/src/…
জিতেন্দ্র নাথ

লিঙ্কের জন্য ধন্যবাদ, সমাধান আমি সেখানে পাওয়া এখনও আমার সমস্যার না viewpager মধ্যে পুরোপুরি অনুভূমিক সোয়াইপ করে, দিয়েছেন তাই আমি এটা একটু পেতে পরিবর্তিত এটা কাজ: stackoverflow.com/a/33696740/2093236
Dmide

15

এখানে একটি সমাধান:

    mPager.setOnTouchListener(new View.OnTouchListener() {

        int dragthreshold = 30;
        int downX;
        int downY;

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getRawX();
                downY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                int distanceX = Math.abs((int) event.getRawX() - downX);
                int distanceY = Math.abs((int) event.getRawY() - downY);

                if (distanceY > distanceX && distanceY > dragthreshold) {
                    mPager.getParent().requestDisallowInterceptTouchEvent(false);
                    mScrollView.getParent().requestDisallowInterceptTouchEvent(true);
                } else if (distanceX > distanceY && distanceX > dragthreshold) {
                    mPager.getParent().requestDisallowInterceptTouchEvent(true);
                    mScrollView.getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                mScrollView.getParent().requestDisallowInterceptTouchEvent(false);
                mPager.getParent().requestDisallowInterceptTouchEvent(false);
                break;
            }
            return false;
        }
    });

আপনি নীচে চাপলে মূলত এক্স, ওয়াই মান নির্ধারণ করে এবং আমরা কোন পথে যেতে চাই তা নির্ধারণের জন্য টেনে আনার সময় দূরত্ব গণনা করে। আপনার কেসটির জন্য অনুকূলিত করার জন্য ড্রাগথ্রেসোল্ডের সাথে চারপাশে খেলুন।


আমার একই সমস্যা ছিল .এই একমাত্র সমাধানটি কাজ করেছিল। ভাল কাজ ... :)
Rawcoder064

এটি আমার পক্ষে সেরা সমাধান। এটি স্ক্রোলভিউটিকে উপরে এবং নীচে স্লাইডিং করতে বিরক্ত করবে না।
লই গুও

এটি আমার পক্ষে সেরা সমাধান। এছাড়াও আমাদের কাছে এই সমাধানটিতে প্রান্তিক মানটি কনফিগার করার বিকল্প রয়েছে।
বিনয়াক

আমার পক্ষে কাজ করে না, কারণ এই বাতিলকরণের বিবৃতিটি পৌঁছানোর আগে
স্ক্রোলভিউ স্পর্শটিকে

দুর্দান্ত কাজ, এবং যদি আপনি এটি র‍্যাপকন্টেন্টভিউজারের সাথে ব্যবহার করতে চান তবে এটিও খুব ভালভাবে কাজ করছে
সিলভান্স সোলঙ্কি

4

ভিউপ্যাজারের সাহায্যে আপনি পৃষ্ঠা-পরিবর্তন ইভেন্টগুলি ক্যাপচার করতে পারেন এবং স্ক্রোলভিউকে পৃষ্ঠার পরিবর্তনের কারণে স্পর্শ ইভেন্টটিকে বাধা দিতে বাধা দিতে পারেন।

এটি খুব সহজ, ব্যবহার করে ViewGroup.requestDisallowInterceptTouchEvent(boolean)। এটি ব্যবহারকারীর ভিউপ্যাজারে একটি টানা শুরু করা সত্ত্বেও স্ক্রোলভিউটিকে টেনে আনতে দেয়, তবে পেজারে অনুভূমিক টানাটি এখনও স্ক্রোলভিউ হস্তক্ষেপ ছাড়াই কাজ করবে।

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Add android:id for your ScrollView in your layout
        final ScrollView sv = (ScrollView) findViewById(R.id.scrollview);
        final ViewPager vp = (ViewPager) findViewById(R.id.viewpager);
        vp.setAdapter(new MyPagerAdapter(this));

        // Use a page-change listener to respond to begin-drag events:
        vp.setOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageSelected(int newState) {
                if (newState == ViewPager.SCROLL_STATE_DRAGGING) {
                    // Prevent the ScrollView from intercepting this event now that the page is changing.
                    // When this drag ends, the ScrollView will start accepting touch events again.
                    sv.requestDisallowInterceptTouchEvent(true);
                }
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });

    }

এটি আমার জন্য অ্যান্ড্রয়েড ২.৩.৪ এবং ৪.২.১ এ অ্যান্ড্রয়েড সাপোর্ট ভি 4 লাইব্রেরি সহ কাজ করে।


4
এটি কি পেজস্লিকটেডের পরিবর্তে পেজস্ক্রোলস্টেট চেঞ্জ হওয়ার কথা?
ক্রেগারস

2

আমি @ মিশেল হার্বিগের কাছ থেকে সমাধানটি রূপান্তরিত করেছি এর সুবিধাটি হ'ল এটি যে কোনও ভিউতে কাজ করে যা setOnTouchListenerকেবলমাত্র ভিউপাগার নয় (উদাহরণস্বরূপ ভিউপেইজারআইডিকেটর) এবং এটি একটি স্ব-অন্তর্ভুক্ত শ্রেণি।

ব্যবহারের উদাহরণ:

// runStatsPager is a android.support.v4.view.ViewPager;
runStatsPager.setOnTouchListener(new ViewInScrollViewTouchHelper(runStatsPager));

// runStatsPagerIndicator is a com.viewpagerindicator.TitlePageIndicator
runStatsPagerIndicator.setOnTouchListener(new ViewInScrollViewTouchHelper(runStatsPagerIndicator));

এবং শ্রেণি:

class ViewInScrollViewTouchHelper implements View.OnTouchListener {

    private final ScrollView scrollView;
    private final View viewInScrollView;
    int dragthreshold = 30;
    int downX;
    int downY;

    public ViewInScrollViewTouchHelper(View viewInScrollView) {

        if (viewInScrollView == null) {
            throw new IllegalArgumentException("viewInScrollView cannot be null.");
        }

        ViewParent parent = viewInScrollView.getParent();
        ScrollView scrollView = null;
        do {
            if (parent instanceof ScrollView) {
                scrollView = (ScrollView) parent;
                break;
            }
        } while(parent != null && (parent = parent.getParent()) != null);

        if (scrollView == null) {
            throw new IllegalArgumentException("View does not have a ScrollView in its parent hierarchy.");
        }

        this.scrollView = scrollView;
        this.viewInScrollView = viewInScrollView;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getRawX();
                downY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                int distanceX = Math.abs((int) event.getRawX() - downX);
                int distanceY = Math.abs((int) event.getRawY() - downY);

                if (distanceY > distanceX && distanceY > dragthreshold) {
                    viewInScrollView.getParent().requestDisallowInterceptTouchEvent(false);
                    scrollView.getParent().requestDisallowInterceptTouchEvent(true);
                } else if (distanceX > distanceY && distanceX > dragthreshold) {
                    viewInScrollView.getParent().requestDisallowInterceptTouchEvent(true);
                    scrollView.getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                scrollView.getParent().requestDisallowInterceptTouchEvent(false);
                viewInScrollView.getParent().requestDisallowInterceptTouchEvent(false);
                break;
        }
        return false;
    }
}

1
public class WrapContentHeightViewPager extends ViewPager {

public WrapContentHeightViewPager(Context context) {
    super(context);
}

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

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int height = 0;
    for (int i = 0; i < getChildCount(); i++) {
        View child = getChildAt(i);
        child.measure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

        int h = child.getMeasuredHeight();
        if (h > height) height = h;
    }

    heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

}

@ ওভাররাইড পাবলিক বুলিয়ান অন টাচ (দেখুন ভি, মোশনইভেন্ট ইভেন্ট) {

    int dragthreshold = 30;
    int downX = 0;
    int downY = 0;

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downX = (int) event.getRawX();
            downY = (int) event.getRawY();
            break;
        case MotionEvent.ACTION_MOVE:
            int distanceX = Math.abs((int) event.getRawX() - downX);
            int distanceY = Math.abs((int) event.getRawY() - downY);

            if (distanceY > distanceX && distanceY > dragthreshold) {
                mViewPager.getParent().requestDisallowInterceptTouchEvent(false);
                mScrollView.getParent().requestDisallowInterceptTouchEvent(true);
            } else if (distanceX > distanceY && distanceX > dragthreshold) {
                mViewPager.getParent().requestDisallowInterceptTouchEvent(true);
                mScrollView.getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        case MotionEvent.ACTION_UP:
            mScrollView.getParent().requestDisallowInterceptTouchEvent(false);
            mViewPager.getParent().requestDisallowInterceptTouchEvent(false);
            break;
    }
    return false;

}

উপরের দুটি ব্যবহার করুন এবং এটি খুব সুন্দরভাবে কাজ করবে। আমি আমার কোডটিও ব্যবহার করেছি।


1

সুতরাং এই পদ্ধতির সাহায্যে আমি (পিতামাতা) ইভেন্টটি চুরি করে এবং বর্তমান স্ক্রোলটি বাতিল না করে কোনও চিন্তা না করেই দিকটিকে ViewPagerস্ক্রোলটিকে Xদিকে দিকে যেতে ScrollViewদিলাম। আরও গুরুত্বপূর্ণ বিষয়, এটি সেই অঞ্চলটি ছেড়ে দেয় যেখানে দিকটি ViewPagerস্ক্রোলযোগ্য অবস্থিত Y

public class CustomViewPager extends ViewPager {

private GestureDetector     mGestureDetector;
View.OnTouchListener        mGestureListener;

public CustomViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    mGestureDetector = new GestureDetector(context, new Detector());
}

@Override
public boolean onTouchEvent(MotionEvent motionEvent) {

    mGestureDetector.onTouchEvent(motionEvent);
    return super.onTouchEvent(motionEvent);
}

class Detector extends SimpleOnGestureListener {

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

        requestDisallowInterceptTouchEvent(true);

        return false;
    }
}
}

দুর্ভাগ্যের ধরনের এখানে সাবক্লাস ভিউপ্যাজারের কাছে of আমি ধারণা করি এটিকে কোনও ভিউতে রূপান্তর করা যেতে পারে nঅনটাইচলিস্টনার। আমি আপাতত উজ্জীবিত!
জন উইলিস

0

এখানে কোনও সমাধানই আমার পক্ষে ভাল কাজ করেনি কারণ এটি হয় ViewPager'টাচ লজিক ScrollView' বা 'যুক্তি'র সংশোধন। আমি উভয় বাস্তবায়ন করতে হবে, এখন এটি একটি কবজ মত কাজ করে।

public class TouchGreedyViewPager extends ViewPager {
    private float xDistance, yDistance, lastX, lastY;

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                xDistance = yDistance = 0f;
                lastX = ev.getX();
                lastY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                final float curX = ev.getX();
                final float curY = ev.getY();
                xDistance += Math.abs(curX - lastX);
                yDistance += Math.abs(curY - lastY) / 3; // favor X events
                lastX = curX;
                lastY = curY;
                if (xDistance > yDistance) {
                    return true;
                }
        }

        return super.onInterceptTouchEvent(ev);
    }
}

public class TouchHumbleScrollView extends ScrollView {
    private float xDistance, yDistance, lastX, lastY;

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                xDistance = yDistance = 0f;
                lastX = ev.getX();
                lastY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                final float curX = ev.getX();
                final float curY = ev.getY();
                xDistance += Math.abs(curX - lastX);
                yDistance += Math.abs(curY - lastY) / 3; // favor X events
                lastX = curX;
                lastY = curY;
                if (xDistance > yDistance) {
                    return false;
                }
        }

        return super.onInterceptTouchEvent(ev);
    }
}

-1

আপনি প্রতিটি পৃষ্ঠায় একটি স্ক্রোলভিউ যুক্ত করে আপনার পেজারআডাপ্টার শ্রেণিতে ইনস্ট্যান্ট আইটেম পদ্ধতি ওভাররাইড করতে পারেন। এখানে একটি কোড:

@Override
public Object instantiateItem(View collection, int position) {
    ScrollView sc = new ScrollView(cxt);
    sc.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    sc.setFillViewport(true);
    TextView tv = new TextView(cxt);
    tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    tv.setText(pages[position]);
    tv.setPadding(5,5,5,5);         
    sc.addView(tv);
    ((ViewPager) collection).addView(sc);

    return sc;
    }

দয়া করে এখানে সবচেয়ে গুরুত্বপূর্ণ পয়েন্টগুলি যোগ করুন বা উদ্ধৃত করুন ote লিঙ্ক পচা হয়।
DegDwight
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.