实现滚动以选择项目ListView

时间:2016-10-16 15:01:32

标签: android listview

我想使用ListView滚动列表来选择项目。 它应该像Seekbar但拇指应该固定,你必须使用它来调整它。我面临的一个问题是,我不知道如何调用这种小部件,这让我很难搜索。所以我在下面制作了这张图片给你一个更好的主意。公平地说,我甚至不知道这是否是这种功能的正确标题。

enter image description here

我通常在时钟设置中看到这种界面(见下图)

enter image description here

1 个答案:

答案 0 :(得分:1)

使用RecyclerView而不是ListView,在https://stackoverflow.com/a/38411582/5887320处引用水平滚动。

这是我自定义代码以获得有效的滚动:
enter image description here

1.dimens.xml

<dimen name="item_dob_width">100dp</dimen>
<dimen name="item_dob_height">50dp</dimen>

<强> 2.recyclerview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center">

    <TextView
        android:id="@+id/tv_year"
        android:layout_width="@dimen/item_dob_width"
        android:layout_height="@dimen/item_dob_height"
        android:textColor="@android:color/white"
        android:background="@android:color/darker_gray"
        android:textSize="28sp"
        android:gravity="center"/>

</LinearLayout>

<强> 3.recyclerview.xml

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"/>

</LinearLayout>

<强> 4.MainActivity.java

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;
import java.util.ArrayList;

public class MainActivity extends Activity{

private static final String TAG = MainActivity.class.getSimpleName();

public float firstItemHeightDate;
public float paddingDate;
public float itemHeightDate;
public int allPixelsDate;
public int finalHeightDate;
private DateAdapter dateAdapter;
private ArrayList<LabelerDate> labelerDates = new ArrayList<>();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.recyclerview);

    getRecyclerviewDate();
}


public void getRecyclerviewDate() {
    final RecyclerView recyclerViewDate = (RecyclerView) findViewById(R.id.recycler_view);
    if (recyclerViewDate != null) {
        recyclerViewDate.postDelayed(new Runnable() {
            @Override
            public void run() {
                setDateValue();
            }
        }, 300);
        /*recyclerViewDate.postDelayed(new Runnable() {
            @Override
            public void run() {
                recyclerViewDate.smoothScrollToPosition(dateAdapter.getItemCount()-1);
                setDateValue();
            }
        }, 5000);*/
    }
    ViewTreeObserver vtoDate = recyclerViewDate.getViewTreeObserver();
    vtoDate.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            recyclerViewDate.getViewTreeObserver().removeOnPreDrawListener(this);
            finalHeightDate = recyclerViewDate.getMeasuredHeight();
            itemHeightDate = getResources().getDimension(R.dimen.item_dob_height);
            paddingDate = (finalHeightDate - itemHeightDate) / 2;
            firstItemHeightDate = paddingDate;
            allPixelsDate = 0;

            final LinearLayoutManager dateLayoutManager = new LinearLayoutManager(getApplicationContext());
            dateLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
            recyclerViewDate.setLayoutManager(dateLayoutManager);
            recyclerViewDate.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    synchronized (this) {
                        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                            calculatePositionAndScrollDate(recyclerView);
                        }
                    }

                }

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    allPixelsDate += dy;
                }
            });
            if (labelerDates == null) {
                labelerDates = new ArrayList<>();
            }
            genLabelerDate();
            dateAdapter = new DateAdapter(labelerDates, (int) firstItemHeightDate);
            recyclerViewDate.setAdapter(dateAdapter);
            dateAdapter.setSelecteditem(dateAdapter.getItemCount() - 1);
            return true;
        }
    });
}

private void genLabelerDate() {
    for (int i = 0; i < 32; i++) {
        LabelerDate labelerDate = new LabelerDate();
        labelerDate.setNumber(Integer.toString(i));
        labelerDates.add(labelerDate);

        if (i == 0 || i == 31) {
            labelerDate.setType(DateAdapter.VIEW_TYPE_PADDING);
        } else {
            labelerDate.setType(DateAdapter.VIEW_TYPE_ITEM);
        }
    }
}
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/

private void calculatePositionAndScrollDate(RecyclerView recyclerView) {
    int expectedPositionDate = Math.round((allPixelsDate + paddingDate - firstItemHeightDate) / itemHeightDate);

    if (expectedPositionDate == -1) {
        expectedPositionDate = 0;
    } else if (expectedPositionDate >= recyclerView.getAdapter().getItemCount() - 2) {
        expectedPositionDate--;
    }
    scrollListToPositionDate(recyclerView, expectedPositionDate);

}

/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/
private void scrollListToPositionDate(RecyclerView recyclerView, int expectedPositionDate) {
    float targetScrollPosDate = expectedPositionDate * itemHeightDate + firstItemHeightDate - paddingDate;
    float missingPxDate = targetScrollPosDate - allPixelsDate;
    if (missingPxDate != 0) {
        //recyclerView.smoothScrollBy((int) missingPxDate, 0);//horizontal
          recyclerView.smoothScrollBy(0, (int) missingPxDate);//virtical
    }
    setDateValue();
}

//
private void setDateValue() {
    int expectedPositionDateColor = Math.round((allPixelsDate + paddingDate - firstItemHeightDate) / itemHeightDate);
    int setColorDate = expectedPositionDateColor + 1;
    //set color here
    dateAdapter.setSelecteditem(setColorDate);
}


public class DateAdapter extends RecyclerView.Adapter<DateAdapter.DateViewHolder> {
    private ArrayList<LabelerDate> dateDataList;


    private static final int VIEW_TYPE_PADDING = 1;
    private static final int VIEW_TYPE_ITEM = 2;
    private int paddingHeightDate = 0;

    private int selectedItem = -1;

    public DateAdapter(ArrayList<LabelerDate> dateData, int paddingHeightDate) {
        this.dateDataList = dateData;
        this.paddingHeightDate = paddingHeightDate;

    }


    @Override
    public DateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_ITEM) {
            final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item,
                    parent, false);
            return new DateViewHolder(view);
        } else {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item,
                    parent, false);

            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
            layoutParams.height = paddingHeightDate;
            view.setLayoutParams(layoutParams);
            return new DateViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(DateViewHolder holder, int position) {
        LabelerDate labelerDate = dateDataList.get(position);
        if (getItemViewType(position) == VIEW_TYPE_ITEM) {
            holder.tvDate.setText(labelerDate.getNumber());
            holder.tvDate.setVisibility(View.VISIBLE);

            Log.d(TAG, "default " + position + ", selected " + selectedItem);
            if (position == selectedItem) {
                Log.d(TAG, "center" + position);
                holder.tvDate.setTextColor(Color.parseColor("#76FF03"));
                holder.tvDate.setTextSize(35);

            } else {
                holder.tvDate.setTextColor(Color.BLACK);
                holder.tvDate.setTextSize(18);
            }
        } else {
            holder.tvDate.setVisibility(View.INVISIBLE);
        }
    }

    public void setSelecteditem(int selecteditem) {
        this.selectedItem = selecteditem;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        return dateDataList.size();
    }

    @Override
    public int getItemViewType(int position) {
        LabelerDate labelerDate = dateDataList.get(position);
        if (labelerDate.getType() == VIEW_TYPE_PADDING) {
            return VIEW_TYPE_PADDING;
        } else {
            return VIEW_TYPE_ITEM;
        }

    }


    public class DateViewHolder extends RecyclerView.ViewHolder {
        public TextView tvDate;

        public DateViewHolder(View itemView) {
            super(itemView);
            tvDate = (TextView) itemView.findViewById(R.id.tv_year);
        }
    }
}

private class LabelerDate {
    private int type;
    private String number;

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}
}