在片段或对话框片段中,在ListView上未检测到滑动

时间:2016-09-26 21:50:40

标签: android listview swipe

由于某些原因,在listView项目上滑动时未检测到滑动。我发现这个功能在正常活动中有效,但是当在片段或对话框片段中时,"轻扫以删除"功能不起作用,我需要在一个片段中,所以我想看看是否有人知道如果可能的话如何让这个在片段中工作。我从https://github.com/JohannBlake/ListViewOrderAndSwipe

获得了代码

这是我的代码中的实现: 我在对话框片段中有listView UserFavoritesDialogFragment.java

public class UserFavoritesDialogFragment extends DialogFragment {
    private final String TAG_LOG = "User Favorites";
    private final String TAG_BOTTOM_VIEW = "BottomView";

    private ArrayList<Person> mPersons = new ArrayList<>();
    private PersonAdapter mAdapterPerson;
    private PersonListViewOrder mPersonsListView;
    private ViewGroup mSwipedViewGroup;
    private JBHorizontalSwipe mJBHorizontalSwipe;

    private boolean mRemovePrevDeleted;
    private Person mPrevDeletedPerson;
    Context mContext;

    static UserFavoritesDialogFragment newInstance(Context context) {
        Context mContext = context;
        UserFavoritesDialogFragment f = new UserFavoritesDialogFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        f.setArguments(args);

        return f;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View vdialog = inflater.inflate(R.layout.user_favorites, container, false);
        getDialog().setTitle("User Favorites");

        Log.d("User Favorites Dialog: ", "Horizontal Swipe before: " + mJBHorizontalSwipe);
        // The main activity needs a HorizontalSwipe object to handle swiping listview items.
        mJBHorizontalSwipe = new JBHorizontalSwipe(ijbHorizontalSwipe);
        Log.d("User Favorites Dialog: ", "Horizontal Swipe after: " + mJBHorizontalSwipe);

        // Add some data to the listview.
        mPersons.add(new Person(getNewId(), "Ben", BitmapFactory.decodeResource(getResources(), R.drawable.ic_ben)));
        mPersons.add(new Person(getNewId(), "Brad", BitmapFactory.decodeResource(getResources(), R.drawable.ic_brad)));
        mPersons.add(new Person(getNewId(), "Bradley", BitmapFactory.decodeResource(getResources(), R.drawable.ic_bradley)));
        mPersons.add(new Person(getNewId(), "Bruce", BitmapFactory.decodeResource(getResources(), R.drawable.ic_bruce)));
        mPersons.add(new Person(getNewId(), "Chris", BitmapFactory.decodeResource(getResources(), R.drawable.ic_chris)));
        mPersons.add(new Person(getNewId(), "Christian", BitmapFactory.decodeResource(getResources(), R.drawable.ic_christian)));
        mPersons.add(new Person(getNewId(), "Denzel", BitmapFactory.decodeResource(getResources(), R.drawable.ic_denzel)));
        mPersons.add(new Person(getNewId(), "George", BitmapFactory.decodeResource(getResources(), R.drawable.ic_george)));
        mPersons.add(new Person(getNewId(), "Hugh", BitmapFactory.decodeResource(getResources(), R.drawable.ic_hugh)));
        mPersons.add(new Person(getNewId(), "Johnny", BitmapFactory.decodeResource(getResources(), R.drawable.ic_johnny)));
        mPersons.add(new Person(getNewId(), "Leo", BitmapFactory.decodeResource(getResources(), R.drawable.ic_leo)));
        mPersons.add(new Person(getNewId(), "Liam", BitmapFactory.decodeResource(getResources(), R.drawable.ic_liam)));
        mPersons.add(new Person(getNewId(), "Matt", BitmapFactory.decodeResource(getResources(), R.drawable.ic_matt)));
        mPersons.add(new Person(getNewId(), "Matthew", BitmapFactory.decodeResource(getResources(), R.drawable.ic_matthew)));
        mPersons.add(new Person(getNewId(), "Morgan", BitmapFactory.decodeResource(getResources(), R.drawable.ic_morgan)));
        mPersons.add(new Person(getNewId(), "Russell", BitmapFactory.decodeResource(getResources(), R.drawable.ic_russell)));
        mPersons.add(new Person(getNewId(), "Tom", BitmapFactory.decodeResource(getResources(), R.drawable.ic_tom)));
        mPersons.add(new Person(getNewId(), "Will", BitmapFactory.decodeResource(getResources(), R.drawable.ic_will)));
        Log.d("User Favorites Dialog: ", "Person Array: " + mPersons);
        mPersonsListView = (PersonListViewOrder) vdialog.findViewById(R.id.lvPersons);
        mPersonsListView.setPersonList(mPersons);
        mAdapterPerson = new PersonAdapter(getActivity(), R.layout.person_item, mPersons, mJBHorizontalSwipe, mPersonsListView, new IListItemControls() {
            @Override
            public void onUndoClicked(View v) {
                // When the Undo button on a list item is pressed, we need to reset the state of deletion.
                mRemovePrevDeleted = false;
                mPrevDeletedPerson = null;
            }
        });

        mPersonsListView.setAdapter(mAdapterPerson);

        mPersonsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // This is where you put your code to handle the user tapping on a list item, i.e.
                // when the item's top view is being displayed.
                Person person = (Person) view.getTag();
                Toast.makeText(getActivity(), person.name, Toast.LENGTH_SHORT).show();
            }
        });

        // Handles removing a deleted item if the user scrolls the listview.
        // NOTE: Don't use a ScrollListener on the listview as this will cause bad
        // side effects. Motion events for the listview must be handled by the
        // onTouchEvent method in PersonListViewOrder in order for this kind of listview
        // to function properly.
        mPersonsListView.setVerticalScrollCallback(new PersonListViewOrder.IVerticalScrollCallback() {
            @Override
            public void onVerticalScroll() {
                // This method gets called when the user scrolls the listview vertically.
                if (mPrevDeletedPerson != null) {
                    int pos = mAdapterPerson.getPosition(mPrevDeletedPerson);
                    View vPrevDeleted = mPersonsListView.getChildAt(pos - mPersonsListView.getFirstVisiblePosition());
                    mAdapterPerson.animateRemoval(vPrevDeleted);
                    mRemovePrevDeleted = false;
                    mPrevDeletedPerson = null;
                }
            }
        });



        return vdialog;
    }

    /**
     * Used to handle callbacks when the user swipes list items.
     */
    private JBHorizontalSwipe.IJBHorizontalSwipe ijbHorizontalSwipe = new JBHorizontalSwipe.IJBHorizontalSwipe() {
        @Override
        public void onReposition(float x, boolean scrollingRight, float scrollDelta) {
            // Currently not used. You can use this callback to do something while the user is swiping a list item.
        }

        @Override
        public void onTopViewVisibilityChange(View vTop, boolean visible) {
            // This callback gets called when the list item's top view changes from fully visible to
            // fully invisible.

            mSwipedViewGroup = (ViewGroup) vTop.getParent();
            final Person person = (Person) mSwipedViewGroup.getTag();
            person.deleted = !visible;
            mRemovePrevDeleted = false;

            // Using setPressed is necessary in various places throughout the app in order
            // to restore the background color of the top view. This is required because list
            // items don't receive the ACTION_UP event which would normally restore the background
            // color. The ACTION_UP is not received because code in PersonListViewOrder as well
            // JBHorizontalSwipe and CustomListItem intercept the motion events and take over
            // control when a ACTION_DOWN is received.

            vTop.setPressed(false);
            mPersonsListView.setPressed(false);

            if ((person == mPrevDeletedPerson) && !person.deleted)
                mPrevDeletedPerson = null;

            if ((person.deleted) && (mPrevDeletedPerson != null) && (person != mPrevDeletedPerson))
                mRemovePrevDeleted = true;

            View vBottom = mSwipedViewGroup.findViewWithTag(TAG_BOTTOM_VIEW);
            PropertyValuesHolder pvhAlphaCurrent;

            ButtonBottomView btnUndo = (ButtonBottomView) vBottom.findViewById(R.id.btnUndo);
            mAdapterPerson.onItemSwiped(person, btnUndo);

            // If the top view is swiped out of view, we want to animate the bottom view's
            // visibility to gradually show, which is done by changing its alpha.

            if (person.deleted)
                pvhAlphaCurrent = PropertyValuesHolder.ofFloat("alpha", 0, 1);
            else
                pvhAlphaCurrent = PropertyValuesHolder.ofFloat("alpha", 1, 0);

            ObjectAnimator animatorView = ObjectAnimator.ofPropertyValuesHolder(vBottom, pvhAlphaCurrent);
            animatorView.setInterpolator(new LinearInterpolator());
            animatorView.setDuration(300);

            animatorView.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    // If a previous item has been deleted but is still visible, we
                    // need to remove it from the list using some animation.

                    if (mRemovePrevDeleted) {
                        int pos = mAdapterPerson.getPosition(mPrevDeletedPerson);

                        if ((pos >= mPersonsListView.getFirstVisiblePosition()) && (pos <= mPersonsListView.getLastVisiblePosition())) {
                            View vPrevDeleted = mPersonsListView.getChildAt(pos - mPersonsListView.getFirstVisiblePosition());
                            mAdapterPerson.animateRemoval(vPrevDeleted);
                        } else {
                            mAdapterPerson.remove(mPrevDeletedPerson);
                        }
                    }

                    if (person.deleted)
                        mPrevDeletedPerson = person;
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                }

                @Override
                public void onAnimationRepeat(Animator animation) {
                }
            });

            animatorView.start();
        }
    };


    /**
     * Used to intercept touch events. THIS LOOKS LIKE IT NEEDS TO BE CALLED TO HANDLE THE SWIPE BUT ITS NEVER CALLED. WHY IS THIS?
     */
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("User Favorites Dialog: ", "Touch event dispatch called ");
        if (mJBHorizontalSwipe != null)
            mJBHorizontalSwipe.onRootDispatchTouchEventListener(ev);

        return super.getActivity().dispatchTouchEvent(ev);
    }


    /**
     * Generates a unique ID.
     *
     * @return Returns a random number.
     */
    private long getNewId() {
        Random r = new Random();
        return r.nextLong();
    }

    interface IListItemControls {
        /**
         * A callback that gets called when the user taps on the Undo button.
         *
         * @param v The view that represents the Undo button.
         */
        void onUndoClicked(View v);
    }
}

JBHorizo​​ntalSwipe.java

public class JBHorizontalSwipe {
    private final String LOG_TAG = "JBHorizontalSwipe";
    private final String TAG_TOP_VIEW = "TopView";

    private boolean mFingerUp;
    private float mScrollDeltaX;
    private float mScrollDeltaY;
    private float mMotionEventPrevX;
    private float mMotionEventPrevY;
    private boolean mScrollingRight;
    private View mScrollerView;
    private IJBHorizontalSwipe mIJBHorizontalSwipe;
    private ObjectAnimator mAnimatorView;
    private boolean mAnimating;
    private boolean mCancelAnimation;
    private float mInitialLeft;
    private boolean mTopViewChanged;
    private boolean mTopViewVisible;

    public final static int ANIMATE_POSITION_LEFT_VISIBLE = 0;
    public final static int ANIMATE_POSITION_LEFT_INVISIBLE = 1;
    public final static int ANIMATE_POSITION_RIGHT_VISIBLE = 2;
    public final static int ANIMATE_POSITION_RIGHT_INVISIBLE = 3;

    public JBHorizontalSwipe(IJBHorizontalSwipe ijbHorizontalSwipe) {
        mIJBHorizontalSwipe = ijbHorizontalSwipe;
    }


    /**
     * Receives motion events from the scroller. Scrollers must implement the dispatchTouchEvent method and call this
     * method from there.
     *
     * @param v     Indicates the scroller that sent the motion event.
     * @param event The motion event that was sent.
     */

    public void onScrollerDispatchTouchEventListener(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.d("User Favorites Dialog: ", "Touch event connected ");
            mScrollerView = v;
            View vTop = mScrollerView.findViewWithTag(TAG_TOP_VIEW);
            mInitialLeft = vTop.getX();
        }else{
            Log.d("User Favorites Dialog: ", "Touch event disconnected ");
        }
    }

    public void onRootDispatchTouchEventListener(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            // Reposition the top view if necessary.
            mFingerUp = true;

            if (mScrollerView != null) {
                View vTop = mScrollerView.findViewWithTag(TAG_TOP_VIEW);

                if ((vTop != null) && (vTop.getX() != 0))
                    processViewPosition(vTop);

                mScrollerView = null;
            }
        } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
            mFingerUp = false;
            mMotionEventPrevX = event.getX();
            mMotionEventPrevY = event.getY();
        }

        if ((event.getAction() == MotionEvent.ACTION_MOVE) && (mScrollerView != null)) {
            // Adjust the position of the view.
            mScrollingRight = event.getX() > mMotionEventPrevX;
            mScrollDeltaX = Math.abs(event.getX() - mMotionEventPrevX);
            mScrollDeltaY = Math.abs(event.getY() - mMotionEventPrevY);
            mMotionEventPrevX = event.getX();
            mMotionEventPrevY = event.getY();

            View vTop = mScrollerView.findViewWithTag(TAG_TOP_VIEW);

            if (((mScrollDeltaX > 10) && (mScrollDeltaY < 10)) || ((vTop != null) && (vTop.getX() != 0))) {
                IJBHorizontalSwipeTouch ijbHorizontalSwipeTouch = (IJBHorizontalSwipeTouch) mScrollerView.getParent();
                ijbHorizontalSwipeTouch.setDisableScrolling(true);

                ListView listview = (ListView) vTop.getParent().getParent();
                listview.requestDisallowInterceptTouchEvent(true);

                repositionTopView();
            }
        }
    }


    /**
     * Repositions the top view when the user scrolls it horizontally.
     */
    private void repositionTopView() {
        View vTop = mScrollerView.findViewWithTag(TAG_TOP_VIEW);

        if (mAnimating || mFingerUp)
            return;

        if (mScrollingRight) {
            float x = vTop.getX() + mScrollDeltaX;

            if (vTop.getX() >= (vTop.getWidth() - 1))
                vTop.setX(-(vTop.getWidth() - 1));
            else
                vTop.setX(x);
        } else {
            float x = vTop.getX() - mScrollDeltaX;

            if (vTop.getX() <= -(vTop.getWidth() - 1))
                vTop.setX(vTop.getWidth());
            else
                vTop.setX(x);
        }

        // Change the alpha of the top view as it is being scrolled making it dimmer as it moves off the screen.
        float alpha = (vTop.getWidth() - Math.abs(vTop.getX() - mScrollDeltaX)) / vTop.getWidth();
        vTop.setAlpha(alpha);
    }


    /**
     * This is where the decision is made to either display or hide the view.
     */
    private void processViewPosition(View vTop) {
        if (mFingerUp) {
            if (mScrollerView == null)
                return;

            if (mScrollingRight && (mScrollDeltaX > 50) && (vTop.getX() > 0)) {
                animateView(vTop, ANIMATE_POSITION_RIGHT_INVISIBLE);
                return;
            }

            if (mScrollingRight && (mScrollDeltaX > 50) && (vTop.getX() < 0)) {
                animateView(vTop, ANIMATE_POSITION_RIGHT_VISIBLE);
                return;
            }

            if (!mScrollingRight && (mScrollDeltaX > 50) && (vTop.getX() > 0)) {
                animateView(vTop, ANIMATE_POSITION_LEFT_VISIBLE);
                return;
            }

            if (!mScrollingRight && (mScrollDeltaX > 50) && (vTop.getX() < 0)) {
                animateView(vTop, ANIMATE_POSITION_LEFT_INVISIBLE);
                return;
            }

            // View was moved to the right of its origin.
            if ((mInitialLeft == 0) && (vTop.getX() > 0) && (vTop.getX() < mScrollerView.getWidth() / 3)) {
                animateView(vTop, ANIMATE_POSITION_LEFT_VISIBLE);
                return;
            } else if ((mInitialLeft == 0) && (vTop.getX() >= mScrollerView.getWidth() / 3)) {
                animateView(vTop, ANIMATE_POSITION_RIGHT_INVISIBLE);
                return;
            } else if ((mInitialLeft == 0) && (vTop.getX() > -mScrollerView.getWidth() / 3)) {
                animateView(vTop, ANIMATE_POSITION_RIGHT_VISIBLE);
                return;
            } else if (mInitialLeft == 0) {
                animateView(vTop, ANIMATE_POSITION_LEFT_INVISIBLE);
                return;
            } else if ((mInitialLeft > 0) && (vTop.getX() >= mScrollerView.getWidth() * 2 / 3)) {
                animateView(vTop, ANIMATE_POSITION_RIGHT_INVISIBLE);
                return;
            } else if (mInitialLeft > 0) {
                animateView(vTop, ANIMATE_POSITION_LEFT_VISIBLE);
                return;
            } else if ((mInitialLeft < 0) && (vTop.getX() > -mScrollerView.getWidth() * 2 / 3)) {
                animateView(vTop, ANIMATE_POSITION_RIGHT_VISIBLE);
                return;
            } else {
                animateView(vTop, ANIMATE_POSITION_LEFT_INVISIBLE);
                return;
            }
        } else {
            if (mAnimatorView != null)
                mAnimatorView.cancel();
        }
    }


    /**
     * Makes the top view visible by animating it onto the screen from either
     * the left or right side of the container depending on where its current
     * left position is located.
     *
     * @param vTop The top view to make visible.
     */
    public void showTopView(View vTop) {
        if (vTop.getX() < 0)
            animateView(vTop, ANIMATE_POSITION_RIGHT_VISIBLE);
        else
            animateView(vTop, ANIMATE_POSITION_LEFT_VISIBLE);

        mTopViewVisible = true;
        mTopViewChanged = true;
    }

    /**
     * Shows or hides the top view by animating on to or off of the screen.
     *
     * @param vTop     The top view.
     * @param position Use ANIMATE_POSITION_LEFT_INVISIBLE to slide it off the screen in the left
     *                 direction. Use ANIMATE_POSITION_RIGHT_INVISIBLE to slide it off the screen
     *                 in the right direction. Set it to ANIMATE_POSITION_LEFT_VISIBLE or
     *                 ANIMATE_POSITION_RIGHT_VISIBLE to slide it on to the screen.
     */
    public void animateView(View vTop, int position) {
        if (mAnimatorView != null)
            mAnimatorView.cancel();

        float left;

        switch (position) {
            case ANIMATE_POSITION_LEFT_INVISIBLE:
                left = -vTop.getWidth();
                break;

            case ANIMATE_POSITION_RIGHT_INVISIBLE:
                left = vTop.getWidth();
                break;

            default:
                left = 0;
                break;
        }

        mAnimating = true;
        PropertyValuesHolder pvhXBar = PropertyValuesHolder.ofFloat("x", vTop.getX(), left);
        mAnimatorView = ObjectAnimator.ofPropertyValuesHolder(vTop, pvhXBar);
        mAnimatorView.setInterpolator(new LinearInterpolator());
        mAnimatorView.setDuration(200);
        mAnimatorView.addListener(animListener);
        mCancelAnimation = false;
        mAnimatorView.start();

        if ((mIJBHorizontalSwipe != null) && (left != mInitialLeft)) {
            mTopViewChanged = true;
            mTopViewVisible = (position == ANIMATE_POSITION_LEFT_VISIBLE) || (position == ANIMATE_POSITION_RIGHT_VISIBLE);
        } else
            mTopViewChanged = false;

    }


    /**
     * The animation listener. Needed to know when the animation should be canceled.
     */
    private Animator.AnimatorListener animListener = new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            if (mCancelAnimation)
                mAnimatorView.cancel();
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            mAnimating = false;
            mCancelAnimation = false;
            View v = (View) mAnimatorView.getTarget();
            v.setAlpha(1);

            if ((mIJBHorizontalSwipe != null) && mTopViewChanged)
                mIJBHorizontalSwipe.onTopViewVisibilityChange(v, mTopViewVisible);
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            mCancelAnimation = false;
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }
    };


    public interface IJBHorizontalSwipe {
        void onReposition(float x, boolean scrollingRight, float scrollDelta);

        void onTopViewVisibilityChange(View vTop, boolean visible);
    }

    public interface IJBHorizontalSwipeTouch {
        void setDisableScrolling(boolean disable);
    }

    public interface IJBHorizontalSwipeAdapter {
        View getSelectedView();
    }
}

user_favorites.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true"
    android:id="@+id/img">

    <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:rowCount="10"
        android:columnCount="2"
        android:padding="10dp"
        android:elevation="1dp"
        android:background="#313131">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="People"
            android:layout_marginTop="10dp"
            android:layout_column="0"
            android:layout_row="0"
            android:id="@+id/textViewPeople2" />

        <View
            android:id="@+id/HorizontalLine1"
            android:layout_width="match_parent"
            android:layout_column="0"
            android:layout_columnSpan="2"
            android:layout_row="1"
            android:layout_height="1dip"
            android:background="#aaa"
            android:layout_marginTop="10dp" />

        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_column="0"
            android:layout_columnSpan="2"
            android:layout_row="2"
            tools:context=".UserFavoritesDialogFragment">


            <view
                android:id="@+id/ListViewBackground"
                class="com.example.rapid.rapid.ListViewItemBackground"
                android:layout_width="match_parent"
                android:layout_height="150dp">

                <com.example.rapid.rapid.PersonListViewOrder
                    android:id="@+id/lvPersons"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:divider="#c0c0c0"
                    android:dividerHeight="1dp"
                    android:scrollingCache="true"/>

            </view>
        </RelativeLayout>
    </GridLayout>
</ScrollView>

1 个答案:

答案 0 :(得分:0)

快速查看表明您可能需要在user_favourite.xml文件的ScrollView中添加android:clickable="true"。可能发生的事情是您的点击或触摸是否泄漏?通过而不被捕获。