滚动列表一次查看一个项目

时间:2016-07-13 06:59:12

标签: android listview scroll android-recyclerview

大家好我想让我的Listview像这样,一个项目一次滚动,顺利。 这里到目前为止我尝试过但没有运气:( 请提前帮助和感谢

enter image description here

自定义ListView类

public class SingleScrollListView extends ListView {
private boolean mSingleScroll = false;
private VelocityTracker mVelocity = null;
final private float mEscapeVelocity = 2000.0f;
final private int mMinDistanceMoved = 20;
private float mStartY = 0;

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

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

public SingleScrollListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public void setSingleScroll(boolean aSingleScroll) {
    mSingleScroll = aSingleScroll;
}

public int getVerticalScrollOffset() {
    return getFirstVisiblePosition();
}

@Override
public boolean dispatchTouchEvent(MotionEvent aMotionEvent) {
    if (aMotionEvent.getAction() == MotionEvent.ACTION_DOWN) {
        if (mSingleScroll && mVelocity == null)
            mVelocity = VelocityTracker.obtain();
        mStartY = aMotionEvent.getY();
        return super.dispatchTouchEvent(aMotionEvent);
    }

    if (aMotionEvent.getAction() == MotionEvent.ACTION_UP) {
        if (mVelocity != null) {
            if (Math.abs(aMotionEvent.getY() - mStartY) > mMinDistanceMoved) {
                mVelocity.computeCurrentVelocity(1000);
                float velocity = mVelocity.getYVelocity();

                if (aMotionEvent.getY() > mStartY) {
                    // always lock
                    if (velocity > mEscapeVelocity) {
                        smoothScrollToPosition(getFirstVisiblePosition());
                    } else {
                        // lock if over half way there
                        View view = getChildAt(0);
                        if (view != null) {
                            if (view.getBottom() >= getHeight() / 2)
                                smoothScrollToPosition(getFirstVisiblePosition());
                            else
                                smoothScrollToPosition(getFirstVisiblePosition() + 1);
                        }
                    }
                } else {
                    if (velocity < -mEscapeVelocity)

                        smoothScrollToPosition(getFirstVisiblePosition() + 1);
                    else {
                        // lock if over half way there
                        View view = getChildAt(1);
                        if (view != null) {

                            if (view.getTop() <= getHeight() / 2)

                                smoothScrollToPosition(getFirstVisiblePosition() + 1);
                            else
                                smoothScrollToPosition(getFirstVisiblePosition());
                        }
                    }
                }
            }
            mVelocity.recycle();
        }
        mVelocity = null;

        if (mSingleScroll) {
            if (Math.abs(aMotionEvent.getY() - mStartY) > mMinDistanceMoved)
                return super.dispatchTouchEvent(aMotionEvent);
        } else
            return super.dispatchTouchEvent(aMotionEvent);
    }

    if (mSingleScroll) {
        if (mVelocity == null) {
            mVelocity = VelocityTracker.obtain();
            mStartY = aMotionEvent.getY();
        }
        mVelocity.addMovement(aMotionEvent);
    }

    return super.dispatchTouchEvent(aMotionEvent);
}

}

自定义适配器

private class CarListAdapter extends ArrayAdapter<CarList> {
public CarListAdapter() {
    super(MainActivity.this, R.layout.list_view_layout, listArray);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View itemView = convertView;

    if (itemView == null) {
        itemView = getLayoutInflater().inflate(R.layout.list_view_layout, parent, false);
    }

    CarList data = listArray.get(position);
    ImageView Image = (ImageView) itemView.findViewById(R.id.image_holder);
    Image.setImageResource(data.getImageID());

    return itemView;
}

}

列表视图布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image_holder"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:scaleType="centerCrop"
        android:src="@drawable/car_1" />

2 个答案:

答案 0 :(得分:3)

我喜欢您应用的用户界面。对于答案部分,我建议您使用viewpager而不是ListView。

这是第一个真正的问题,如何让viewPager滚动垂直?

答案是: - 覆盖触摸事件并使用viewpager变换器来假设垂直寻呼机,如this Answer中所述。

我只是在这里复制片段

/**
 * Uses a combination of a PageTransformer and swapping X & Y coordinates
 * of touch events to create the illusion of a vertically scrolling ViewPager. 
 * 
 * Requires API 11+
 * 
 */
public class VerticalViewPager extends ViewPager {

    public VerticalViewPager(Context context) {
        super(context);
        init();
    }

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

    private void init() {
        // The majority of the magic happens here
        setPageTransformer(true, new VerticalPageTransformer());
        // The easiest way to get rid of the overscroll drawing that happens on the left and right
        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View view, float position) {

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) { // [-1,1]
                view.setAlpha(1);

                // Counteract the default slide transition
                view.setTranslationX(view.getWidth() * -position);

                //set Y position to swipe in from top
                float yPosition = position * view.getHeight();
                view.setTranslationY(yPosition);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

    /**
     * Swaps the X and Y coordinates of your touch event.
     */
    private MotionEvent swapXY(MotionEvent ev) {
        float width = getWidth();
        float height = getHeight();

        float newX = (ev.getY() / height) * width;
        float newY = (ev.getX() / width) * height;

        ev.setLocation(newX, newY);

        return ev;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev){
        boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
        swapXY(ev); // return touch coordinates to original reference frame for any child views
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapXY(ev));
    }

}

看起来像这样

enter image description here

现在,第二部分如何使textView用于成本与页面滑动一起上升

您可以将垂直视图寻呼机与textSwitcher一起使用

costNameSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
    @Override
    public android.view.View makeView() {

        LayoutInflater inflater = LayoutInflater.from(getActivity());
        TextView textView = (TextView) inflater.inflate(R.layout.offer_heading, null);
        return textView;
    }
});

costNameSwitcher.setInAnimation(getActivity(), R.anim.slide_in_up);
costNameSwitcher.setOutAnimation(getActivity(), R.anim.slide_out_up);

并在页面上切换textwitcher中的文本,如下所示

 verticalViewPager
            .addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position,
                                           float positionOffset, int positionOffsetPixels) {

                }

                @Override
                public void onPageSelected(int position) {


                    costNameSwitcher.setText("Some Cost");


                }

                @Override
                public void onPageScrollStateChanged(int state) {

                }
            });

动画

slide_in_up

<?xml version="1.0" encoding="UTF-8"?>
<translate android:toYDelta="0%p" android:fromYDelta="100%p" android:duration="500" xmlns:android="http://schemas.android.com/apk/res/android"/>

slide_out_up

<?xml version="1.0" encoding="UTF-8"?>
<translate android:toYDelta="-100%p" android:fromYDelta="0%p" android:duration="500" xmlns:android="http://schemas.android.com/apk/res/android"/>

ViewPager with views

/**
 * The Class slidingPagerAdapter.
 */
public class slidingPagerAdapter extends PagerAdapter {
    private final List<HotOffer> listOfOffers;
    private Context mContext;
    private LayoutInflater mLayoutInflater;


    /**
     * Instantiates a new home slides pager adapter.
     *
     * @param context       the context
     * @param carousalImage
     */
    public slidingPagerAdapter(Context context, List<HotOffer> carousalImage) {
        mContext = context;
        mLayoutInflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        this.listOfOffers = carousalImage;
    }

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

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

    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        final View itemView = mLayoutInflater.inflate(R.layout.carousal_page, container,
                false);


        Picasso.with(mContext)
                .load(listOfOffers.get(position).getImageUrl())
                .networkPolicy(NetworkPolicy.OFFLINE)
                .fit()
                .centerCrop()
                .into((ImageView) itemView
                        .findViewById(R.id.image), new Callback() {
                    @Override
                    public void onSuccess() {
                    }


                    @Override
                    public void onError() {
                        // Try again online if cache failed
                        Picasso.with(mContext)
                                .load(listOfOffers.get(position).getImageUrl())
                              .fit()
                                .centerCrop()
                                .into((ImageView) itemView
                                        .findViewById(R.id.image));
                    }
                });


        container.addView(itemView);

        return itemView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((FrameLayout) object);
    }
}

显示下一个/上一个视图的一点点

  // Disable clip to padding
            viewPager.setClipToPadding(false);
            // set padding manually, the more you set the padding the more you see of prev & next page
            viewPager.setPadding(40, 0, 40, 0);

结果: -

enter image description here

你不需要设置左边填充即使用

   viewPager.setPadding(40, 0, 0, 0);

答案 1 :(得分:1)

为什么不为此目的使用带有片段的垂直可滚动viewpager。

我正在复制runtime error回复,供您参考。

您可以使用ViewPager.PageTransformer来呈现垂直ViewPager的错觉。要实现垂直而不是水平拖动的滚动,您必须覆盖ViewPager的默认触摸事件,并在处理之前交换MotionEvents的坐标,例如:

    /**
     * Uses a combination of a PageTransformer and swapping X & Y coordinates
     * of touch events to create the illusion of a vertically scrolling ViewPager. 
     * 
     * Requires API 11+
     * 
     */

public class VerticalViewPager extends ViewPager {

public VerticalViewPager(Context context) {
    super(context);
    init();
}

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

private void init() {
    // The majority of the magic happens here
    setPageTransformer(true, new VerticalPageTransformer());
    // The easiest way to get rid of the overscroll drawing that happens on the left and right
    setOverScrollMode(OVER_SCROLL_NEVER);
}

private class VerticalPageTransformer implements ViewPager.PageTransformer {

    @Override
    public void transformPage(View view, float position) {

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        } else if (position <= 1) { // [-1,1]
            view.setAlpha(1);

            // Counteract the default slide transition
            view.setTranslationX(view.getWidth() * -position);

            //set Y position to swipe in from top
            float yPosition = position * view.getHeight();
            view.setTranslationY(yPosition);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

/**
 * Swaps the X and Y coordinates of your touch event.
 */
private MotionEvent swapXY(MotionEvent ev) {
    float width = getWidth();
    float height = getHeight();

    float newX = (ev.getY() / height) * width;
    float newY = (ev.getX() / width) * height;

    ev.setLocation(newX, newY);

    return ev;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev){
    boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
    swapXY(ev); // return touch coordinates to original reference frame for any child views
    return intercepted;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapXY(ev));
}
}

当然,您可以根据需要调整这些设置。