android - 创建类似垂直viewpager的东西

时间:2014-10-06 13:37:51

标签: android android-viewpager vertical-alignment

我希望得到像这样的东西

enter image description here

我已经使用listview做了类似的事情,但我遇到的问题是,在我选择一个项目后,它将没有按下它时的颜色。 还有一个视图寻呼机,我会有一个额外的容器,我可以把我的碎片。

如果像这样的东西会起作用,那就更好了!

enter image description here

Android: Vertical ViewPager 我看过这个,看起来不错,但我也希望在屏幕的左侧有一些项目。

您认为最好的方法是什么? 而且,我已经有了一个导航抽屉,所以不会有新的方法。

2 个答案:

答案 0 :(得分:1)

  

我已经用listview做了类似的事情,但问题是我   我选择一个项目之后就不会有它的颜色了   当它被按下时。

这是一个简单的解决方法。在onClick(View arg0)方法中,添加arg0.setSelected(true)。还要记住将旧视图的选定状态设置为false。

如果存在重复使用视图的风险,则需要通过将数据列表更改为地图并在条目中存储布尔值来跟踪选择的视图。但是,如果您想要将列表和详细片段一起滚动,或者列表足够短,就像您的图片中那样没有必要。

将背景颜色更改为选择器(可绘制的xml)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:color="@color/selected_color_resource"
        android:state_selected="true" />
    <item
        android:color="@color/color_resource" />  <!-- default -->
</selector>

将使用第一个匹配状态,因此请确保默认为最后一个项目。

  

还有一个视图寻呼机,我会有一个额外的容器   可以把我的碎片。

是的,请使用Brett的解决方案。用VerticalViewPager替换您的详细片段。您需要将您的活动(或处理列表的任何类)设置为ViewPager.SimpleOnPageChangeListener。这样当有人滚动所选列表项时可以更改。由于这个很好的方法,你可以做很多很酷的动画

onPageScrolled(int position, float positionOffset, int positionOffsetPixels)

答案 1 :(得分:0)

尝试以下示例,

main.xml中

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <com.brandontate.BTGridPager.BTFragmentGridPager
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/fragmentGridPager"
            android:background="#ffff00"/>

</LinearLayout>

demo_fragment.xml

<?xml version="1.0" encoding="utf-8"?>

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

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|center_horizontal"
            android:id="@+id/label"
            android:textSize="45sp"
            android:textColor="@android:color/black"
            android:layout_centerInParent="true"
            />

</RelativeLayout>

DemoFragment.java

package com.demo.app;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.brandontate.BTGridPager.BTFragmentGridPager;
import com.example.BTGridPager.R;

/**
 * BTGridPager
 *
 * @author Brandon Tate
 */
public class DemoFragment extends Fragment {

    TextView mLabel;

    BTFragmentGridPager.GridIndex mGridIndex;


    public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

        RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.demo_fragment, container, false);
        mLabel = (TextView) layout.findViewById(R.id.label);
        setTxtRow(mGridIndex);

        return layout;

    }


    public void setTxtRow(BTFragmentGridPager.GridIndex gridIndex) {
        mLabel.setText("(" + gridIndex.getRow() + ", " + gridIndex.getCol() + ")");
    }

    public void setGridIndex(BTFragmentGridPager.GridIndex gridIndex){
        mGridIndex = gridIndex;
    }

}

Demo.java

package com.demo.app;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import com.brandontate.BTGridPager.BTFragmentGridPager;
import com.example.BTGridPager.R;

public class Demo extends FragmentActivity {

    private BTFragmentGridPager.FragmentGridPagerAdapter mFragmentGridPagerAdapter;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final BTFragmentGridPager mFragmentGridPager = (BTFragmentGridPager) findViewById(R.id.fragmentGridPager);

        mFragmentGridPagerAdapter = new BTFragmentGridPager.FragmentGridPagerAdapter() {
            @Override
            public int rowCount() {
                return 10;
            }

            @Override
            public int columnCount(int row) {
                return 10;
            }

            @Override
            public Fragment getItem(BTFragmentGridPager.GridIndex index) {
                DemoFragment panelFrag1 = new DemoFragment();
                panelFrag1.setGridIndex(index);

                return panelFrag1;
            }
        };

        mFragmentGridPager.setGridPagerAdapter(mFragmentGridPagerAdapter);
    }
}

BTVerticalPagerFragment.java

package com.brandontate.BTGridPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

/**
 * BTGridPager
 *
 * @author Brandon Tate
 */
public class BTVerticalPagerFragment extends Fragment {

    /** Pager adapter. */
    private FragmentStatePagerAdapter mVerticalPagerAdapter;

    /** Page change listener. */
    private ViewPager.OnPageChangeListener mPageChangeListener;

    /** The actual pager. */
    private BTVerticalPager mPager;

    /** The start page when the pager is loaded. */
    private int mStartPage = 0;

    private BTFragmentGridPager mGridPager;

    public BTVerticalPagerFragment(){

    }

//    public BTVerticalPagerFragment (BTFragmentGridPager gridPager) {
//
//        mGridPager = gridPager;
//    }



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        LinearLayout view = new LinearLayout(getActivity());
        view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
        view.setId(1);

        if (mGridPager != null) {
            mPager = new BTVerticalPager(getActivity(), mGridPager);
            mPager.setId(2);
            mPager.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
            mPager.setAdapter(mVerticalPagerAdapter);
            mPager.setCurrentItem(mStartPage);
            mPager.setOnPageChangeListener(mPageChangeListener);

            view.addView(mPager);
        }

        return view;
    }

    public FragmentStatePagerAdapter getVerticalPagerAdapter() {
        return mVerticalPagerAdapter;
    }

    public void setGridPager(BTFragmentGridPager gridPager){
        mGridPager = gridPager;
    }

    public void setVerticalPagerAdapter(FragmentStatePagerAdapter verticalPagerAdapter) {
        this.mVerticalPagerAdapter = verticalPagerAdapter;

        if (mPager != null)
            mPager.setAdapter(mVerticalPagerAdapter);
    }

    public void setPageChangeListener(ViewPager.OnPageChangeListener pageChangeListener) {
        this.mPageChangeListener = pageChangeListener;

        if (mPager != null)
            mPager.setOnPageChangeListener(mPageChangeListener);
    }

    public BTVerticalPager getPager() {
        return mPager;
    }

    public void setStartPage(int startPage) {
        this.mStartPage = startPage;
    }

}

BTVerticalPager.java

package com.brandontate.BTGridPager;


import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * BTGridPager
 *
 * @author Brandon Tate
 */
public class BTVerticalPager extends ViewPager {

    BTFragmentGridPager mGridPager;

    public BTVerticalPager(Context context, BTFragmentGridPager gridPager) {
        super(context);
        init();

        mGridPager = gridPager;
    }

    public BTVerticalPager(Context context, AttributeSet attrs, BTFragmentGridPager gridPager) {
        super(context, attrs);
        init();

        mGridPager = gridPager;
    }

    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);
    }

    @Override
    protected void onPageScrolled(int position, float offset, int offsetPixels) {
        super.onPageScrolled(position, offset, offsetPixels);

        if (offset == 0  && mGridPager.shouldReset) {
            getRootView().post(new Runnable() {
                @Override
                public void run() {
                    mGridPager.shouldReset = false;
                    mGridPager.resetAdapter();
                }
            });
        }
    }

    private class VerticalPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();
            int pageHeight = view.getHeight();

            view.setAlpha(1);
//
//            if (position < -1 && !mGridPager.shouldReset) { // [-Infinity,-1)
//                // This page is way off-screen to the left.
//                view.setAlpha(0);
//
//            }
            if (position >= -1 && position <= 1) { // [-1,1]
                // Counteract the default slide transition
                view.setTranslationX(pageWidth * -position);

                //set Y position to swipe in from top
                float yPosition = position * pageHeight;
                view.setTranslationY(yPosition);
            }
//            } else if (!mGridPager.shouldReset) { // (1,+Infinity]
//                // This page is way off-screen to the right.
//                view.setAlpha(0);
//            }
        }
    }

    /**
     * Swaps the X and Y coordinates of your touch event
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //swap the x and y coords of the touch event
        ev.setLocation(ev.getY(), ev.getX());

        return super.onTouchEvent(ev);
    }
}

BTFragmentGridPager.java

package com.brandontate.BTGridPager;


import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;


/**
 * BTGridPager
 *
 * The grid pager works by maintaining a view port that moves around a virtual grid.  The views to show in this viewport will be provided by the BTGridPagerAdapter.
 * When the a new page is selected the view port is updated to hold only the views surrounding it.
 *
 * @author Brandon Tate
 */
public class BTFragmentGridPager extends ViewPager {

    /** Bit flag for no wrapping. */
    public static final int GRID_WRAP_NONE = 0;

    /** Bit flag for left side wrapping. */
    public static final int GRID_WRAP_LEFT = 1 << 1;

    /** Bit flag for right side wrapping. */
    public static final int GRID_WRAP_RIGHT = 1 << 2;

    /** Bit flag for top side wrapping. */
    public static final int GRID_WRAP_UP = 1 << 3;

    /** Bit flag for bottom side wrapping. */
    public static final int GRID_WRAP_DOWN = 1 << 4;

    /** Wrapping flag. */
    private int mWrappingFlags = (GRID_WRAP_DOWN | GRID_WRAP_UP | GRID_WRAP_RIGHT);

    /** Bit flag for no resets. */
    public static final int GRID_RESET_NONE = 0;

    /** Bit flag for resetting to first column on row change. */
    public static final int GRID_RESET_ROW = 1 << 1;

    /** Bit flag for resetting to first row on column change. */
    public static final int GRID_RESET_COL = 1 << 2;

    /** Reset Flag. */
    private int mResetFlags = GRID_RESET_NONE;


    /** Current grid index. */
    public GridIndex mCurrentIndex = new GridIndex(0, 0);

    /** The fragment grid pager adapter for retrieving views. */
    private FragmentGridPagerAdapter mGridPagerAdapter;

    /** How many views to load on each side of the central view. */
    private int mGridPadding = 1;

    boolean shouldReset = false;

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


    /**
     * Used to inflate the Workspace from XML.
     *
     * @param context
     *            The application's context.
     * @param attrs
     *            The attribtues set containing the Workspace's customization values.
     */
    public BTFragmentGridPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public void init(){
        resetAdapter();
    }

    //*****************************************************
    //*
    //*         Helpers
    //*
    //*****************************************************

    private boolean canScrollLeft(){
        return  mGridPagerAdapter != null && !(mCurrentIndex.getCol() == 0 && (0 == (mWrappingFlags & GRID_WRAP_LEFT)));
    }

    private boolean canScrollRight(){
        return mGridPagerAdapter != null && !(mCurrentIndex.getCol() == (mGridPagerAdapter.columnCount(mCurrentIndex.getRow()) - 1) && (0 == (mWrappingFlags & GRID_WRAP_RIGHT)));
    }

    private boolean canScrollUp(){
        return  mGridPagerAdapter != null && !(mCurrentIndex.getRow() == 0 && (0 == (mWrappingFlags & GRID_WRAP_UP)));
    }

    private boolean canScrollDown(){
        return  mGridPagerAdapter != null && !(mCurrentIndex.getRow() == (mGridPagerAdapter.rowCount() - 1) && (0 == (mWrappingFlags & GRID_WRAP_DOWN)));
    }

    private GridIndex wrapGridIndex(GridIndex index){

        int newRow = index.getRow();

        if (newRow < 0)
            newRow = mGridPagerAdapter.rowCount() + newRow;
        else if(newRow >= mGridPagerAdapter.rowCount())
            newRow = (mGridPagerAdapter.rowCount() - newRow);

        int newCol = index.getCol();

        if (newCol < 0)
            newCol = mGridPagerAdapter.columnCount(newRow) + newCol;
        else if (newCol >= mGridPagerAdapter.columnCount(newRow))
            newCol = (mGridPagerAdapter.columnCount(newRow) - newCol);

        return new GridIndex(newRow, newCol);
    }

    /**
     *   Completely resets the adapter with updated current grid index.
     *
     *   No access modifier -- package-private
     */
    void resetAdapter(){

        // Clear old on page change listener to avoid unwanted actions
        setOnPageChangeListener(null);

        setAdapter(new FragmentGridHorizontalPagerAdapter(((FragmentActivity) getContext()).getSupportFragmentManager(), this));

        if (!canScrollLeft())
            setCurrentItem(0, false);
        else if(!canScrollRight())
            setCurrentItem(getAdapter().getCount() - 1);
        else
            setCurrentItem(mGridPadding, false);

        setOnPageChangeListener(new SimpleOnPageChangeListener(){

            @Override
            public void onPageSelected(int i) {

                // Default to wrapping index
                int newCol = mCurrentIndex.getCol() + ( -1 * (mGridPadding - i) );

                // Adjust for limited wrapping
                if (!canScrollLeft())
                    newCol = mCurrentIndex.getCol() + i;
                else if(!canScrollRight())
                    newCol--;

                mCurrentIndex = wrapGridIndex( new GridIndex( (0 != (mResetFlags & GRID_RESET_COL) ) ? 0 : mCurrentIndex.getRow() ,  newCol) );

                shouldReset = true;
            }
        });
    }

    @Override
    protected void onPageScrolled(int position, float offset, int offsetPixels) {
        super.onPageScrolled(position, offset, offsetPixels);

        if (offset == 0 && shouldReset) {
            getRootView().post(new Runnable() {
                @Override
                public void run() {
                    shouldReset = false;
                    resetAdapter();
                }
            });

        }
    }

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        return false;
    }

    //*****************************************************
    //*
    //*         Getters/Setters
    //*
    //*****************************************************

    public FragmentGridPagerAdapter getGridPagerAdapter() {
        return mGridPagerAdapter;
    }

    public void setGridPagerAdapter(FragmentGridPagerAdapter gridPagerAdapter) {
        this.mGridPagerAdapter = gridPagerAdapter;
        resetAdapter();
    }

    public int getResetFlags() {
        return mResetFlags;
    }

    public void setResetFlags(int resetFlags) {
        this.mResetFlags = resetFlags;
    }

    public int getWrappingFlags() {
        return mWrappingFlags;
    }

    public void setWrappingFlags(int wrappingFlags) {
        this.mWrappingFlags = wrappingFlags;
    }


    //*****************************************************
    //*
    //*         Adapters
    //*
    //*****************************************************

    public class FragmentGridHorizontalPagerAdapter extends FragmentStatePagerAdapter{

        FragmentManager fm;
        BTFragmentGridPager mGridPager;

        public FragmentGridHorizontalPagerAdapter(FragmentManager fm, BTFragmentGridPager gridPager) {
            super(fm);

            this.fm = fm;
            this.mGridPager = gridPager;
        }

        @Override
        public Fragment getItem(int i) {

            if (mGridPagerAdapter == null)
                return new Fragment();

            // Figure out if this is our vertical pager
            boolean vpFragFlag = false;

            if (!canScrollLeft() &&  i == 0)
                vpFragFlag = true;
            else if(!canScrollRight() && i == (getAdapter().getCount() - 1))
                vpFragFlag = true;
            else if(canScrollLeft() && canScrollRight())
                vpFragFlag = (i == mGridPadding);

            if (vpFragFlag){

                BTVerticalPagerFragment vpFragment = new BTVerticalPagerFragment();
                vpFragment.setGridPager(mGridPager);

                vpFragment.setVerticalPagerAdapter(new FragmentStatePagerAdapter(fm){
                    @Override
                    public Fragment getItem(int i) {

                        if (mGridPagerAdapter == null)
                            return new Fragment();

                        int newCol = mCurrentIndex.getCol();

                        // If it's not the middle one and we need a row reset
                        if (i != mGridPadding && (0 != (mResetFlags & GRID_RESET_ROW) ))
                            newCol = 0;


                        // Default my view index wrapped
                        GridIndex viewIndex = wrapGridIndex(wrapGridIndex( new GridIndex( mCurrentIndex.getRow() + ( -1 * (mGridPadding - i) ), newCol ) ) );

                        // Adjust for limited wrapping
                        if (!canScrollUp() || !canScrollDown()) {
                            if (i == this.getCount() - 1)
                                viewIndex.setRow(mGridPagerAdapter.rowCount() - 1);
                            else
                                viewIndex.setRow(mCurrentIndex.getRow() + i);
                        }

                        return mGridPagerAdapter.getItem(viewIndex);
                    }

                    @Override
                    public int getCount() {
                        return (mGridPadding * 2) + 1;
                    }

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


                if (!canScrollUp())
                    vpFragment.setStartPage(0);
                else if(!canScrollDown())
                    vpFragment.setStartPage(vpFragment.getVerticalPagerAdapter().getCount() - 1);
                else
                vpFragment.setStartPage(mGridPadding);

                vpFragment.setPageChangeListener(new SimpleOnPageChangeListener() {

                    @Override
                    public void onPageSelected(int i) {
                        int newRow = mCurrentIndex.getRow() + ( -1 * (mGridPadding - i) );

                        if (!canScrollUp())
                            newRow = mCurrentIndex.getRow() + i;
                        else if(!canScrollDown())
                            newRow--;

                        int newCol = mCurrentIndex.getCol();

                        // If it's not the middle one and we need a row reset
                        if (i != mGridPadding && (0 != (mResetFlags & GRID_RESET_ROW) ))
                            newCol = 0;

                        mCurrentIndex = wrapGridIndex(new GridIndex(newRow, newCol));

                        shouldReset = true;

                    }

                });

                return vpFragment;
            }
            else{

                // Default my view index wrapped
                GridIndex viewIndex = wrapGridIndex(new GridIndex((0 != (mResetFlags & GRID_RESET_COL) ) ? 0 : mCurrentIndex.getRow(), mCurrentIndex.getCol() + ( -1 * (mGridPadding - i) ) ) );

                // Adjust for limited wrapping
                if (!canScrollLeft() || !canScrollRight())
                    viewIndex.setCol(mCurrentIndex.getCol() + i);

                return mGridPagerAdapter.getItem(viewIndex);
            }
        }

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

        @Override
        public int getCount() {
            return (mGridPadding * 2) + 1;
        }

    }

    public interface FragmentGridPagerAdapter{

        public int rowCount();
        public int columnCount(int row);
        public Fragment getItem(GridIndex index);

    }

    //*****************************************************
    //*
    //*         Data Types
    //*
    //*****************************************************

    public class GridIndex{

        private int mRow = 0, mCol = 0;

        public GridIndex(int row, int col){

            mRow = row;
            mCol = col;

        }

        public int getRow() {
            return mRow;
        }

        public void setRow(int row) {
            this.mRow = row;
        }

        public int getCol() {
            return mCol;
        }

        public void setCol(int col) {
            this.mCol = col;
        }

        @Override
        public String toString() {
            return "GridIndex{" +
                    "mRow=" + mRow +
                    ", mCol=" + mCol +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            GridIndex gridIndex = (GridIndex) o;

            if (mCol != gridIndex.mCol) return false;
            if (mRow != gridIndex.mRow) return false;

            return true;
        }
    }
}