我有一个水平的recycleview,可以滚动和对齐中心。然后,我要底线指示器在单击时指示所选项目。
看起来像这样:
我查看了this library,但它不符合我的要求。
有实现这个想法吗?
更新:我需要保持指示器始终可见,并且在移动到上方位置(如上面的礼物)时可以平滑滚动
答案 0 :(得分:2)
您可以尝试以下代码:
DateTabIndicator.java
public class DateTabIndicator extends FrameLayout implements View.OnClickListener {
private List<Integer> days = new ArrayList<>();
private int selectedPageIndex = 0;
private int selectedDayIndex = 0;
private static final int[] DAY_TV_RES_ID = {R.id.day_mon, R.id.day_tue, R.id.day_wed, R.id.day_thu, R.id.day_fri, R.id.day_sat,
R.id.day_sun};
public DateTabIndicator(@NonNull Context context) {
super(context);
init();
}
public DateTabIndicator(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public DateTabIndicator(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private TextView monFixedIndicator;
private TextView tueFixedIndicator;
private TextView wedFixedIndicator;
private TextView thuFixedIndicator;
private TextView friFixedIndicator;
private TextView satFixedIndicator;
private TextView sunFixedIndicator;
private View lineIndicator;
private ViewPager daysPager;
private DaysPagerAdapter daysPagerAdapter;
private Handler mHandler = new Handler();
private void init() {
addView(LayoutInflater.from(getContext()).inflate(R.layout.date_tab_indicator, this, false));
monFixedIndicator = findViewById(R.id.mon_fixed_indicator);
tueFixedIndicator = findViewById(R.id.tue_fixed_indicator);
wedFixedIndicator = findViewById(R.id.wed_fixed_indicator);
thuFixedIndicator = findViewById(R.id.thu_fixed_indicator);
friFixedIndicator = findViewById(R.id.fri_fixed_indicator);
satFixedIndicator = findViewById(R.id.sat_fixed_indicator);
sunFixedIndicator = findViewById(R.id.sun_fixed_indicator);
lineIndicator = findViewById(R.id.line_indicator);
daysPager = findViewById(R.id.days_pager);
daysPagerAdapter = new DaysPagerAdapter();
daysPager.setAdapter(daysPagerAdapter);
daysPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
selectedPageIndex = position;
mHandler.removeCallbacks(selectDayRunnable);
mHandler.postDelayed(selectDayRunnable,500);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
mHandler.postDelayed(selectDayRunnable,500);
}
class DaysPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return (int) Math.ceil(days.size() / 7f);
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, final int position) {
final View view = LayoutInflater.from(getContext()).inflate(R.layout.days_pager_item, container, false);
TextView dayMonTv = view.findViewById(R.id.day_mon);
TextView dayTueTv = view.findViewById(R.id.day_tue);
TextView dayWedTv = view.findViewById(R.id.day_wed);
TextView dayThuTv = view.findViewById(R.id.day_thu);
TextView dayFriTv = view.findViewById(R.id.day_fri);
TextView daySatTv = view.findViewById(R.id.day_sat);
TextView daySunTv = view.findViewById(R.id.day_sun);
//Setting Day Text
int index = position * 7;
dayMonTv.setText(days.size() > index ? String.valueOf(days.get(index)) : "");
dayTueTv.setText(days.size() > (++index) ? String.valueOf(days.get(index)) : "");
dayWedTv.setText(days.size() > (++index) ? String.valueOf(days.get(index)) : "");
dayThuTv.setText(days.size() > (++index) ? String.valueOf(days.get(index)) : "");
dayFriTv.setText(days.size() > (++index) ? String.valueOf(days.get(index)) : "");
daySatTv.setText(days.size() > (++index) ? String.valueOf(days.get(index)) : "");
daySunTv.setText(days.size() > (++index) ? String.valueOf(days.get(index)) : "");
//Setting Day VISIBILITY
index = position * 7;
dayMonTv.setVisibility(days.size() > index && days.get(index) != 0 ? VISIBLE : INVISIBLE);
dayTueTv.setVisibility(days.size() > ++index && days.get(index) != 0 ? VISIBLE : INVISIBLE);
dayWedTv.setVisibility(days.size() > ++index && days.get(index) != 0 ? VISIBLE : INVISIBLE);
dayThuTv.setVisibility(days.size() > ++index && days.get(index) != 0 ? VISIBLE : INVISIBLE);
dayFriTv.setVisibility(days.size() > ++index && days.get(index) != 0 ? VISIBLE : INVISIBLE);
daySatTv.setVisibility(days.size() > ++index && days.get(index) != 0 ? VISIBLE : INVISIBLE);
daySunTv.setVisibility(days.size() > ++index && days.get(index) != 0 ? VISIBLE : INVISIBLE);
//Setting Selection
dayMonTv.setSelected(false);
dayTueTv.setSelected(false);
dayWedTv.setSelected(false);
dayThuTv.setSelected(false);
dayFriTv.setSelected(false);
daySatTv.setSelected(false);
daySunTv.setSelected(false);
//Setting Click Listener
dayMonTv.setOnClickListener(DateTabIndicator.this);
dayTueTv.setOnClickListener(DateTabIndicator.this);
dayWedTv.setOnClickListener(DateTabIndicator.this);
dayThuTv.setOnClickListener(DateTabIndicator.this);
dayFriTv.setOnClickListener(DateTabIndicator.this);
daySatTv.setOnClickListener(DateTabIndicator.this);
daySunTv.setOnClickListener(DateTabIndicator.this);
view.setTag(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
}
public List<Integer> getDays() {
return days;
}
public void setDays(List<Integer> days) {
this.days = days;
daysPagerAdapter.notifyDataSetChanged();
}
private View prevDayTv = null;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.day_mon:
selectDay(v, 0);
break;
case R.id.day_tue:
selectDay(v, 1);
break;
case R.id.day_wed:
selectDay(v, 2);
break;
case R.id.day_thu:
selectDay(v, 3);
break;
case R.id.day_fri:
selectDay(v, 4);
break;
case R.id.day_sat:
selectDay(v, 5);
break;
case R.id.day_sun:
selectDay(v, 6);
break;
}
}
/**
* @param dayIndex 0-6
*/
private void selectDay(View v, int dayIndex) {
selectedDayIndex = dayIndex;
int dayListIndex = selectedPageIndex * 7 + dayIndex;
if (prevDayTv != null) prevDayTv.setSelected(false);
v.setSelected(true);
prevDayTv = v;
int[] location = new int[2];
v.getLocationOnScreen(location);
int center_point = location[0]%getWidth() + v.getWidth() / 2;
lineIndicator.animate().x(center_point - lineIndicator.getWidth() / 2);
if (days.size() > dayListIndex && days.get(dayListIndex)!=0) {
//listener
} else {
for (int i = 0; i < 7; i++) {
dayListIndex = selectedPageIndex * 7 + i;
if (days.get(dayListIndex)==1 || days.size()-1 == dayListIndex) {
setSelectedDay(i);
break;
}
}
}
}
/**
* @param dayIndex 0-6
*/
public void setSelectedDay(int dayIndex) {
if (dayIndex >= 0 && dayIndex < 7) {
selectedDayIndex = dayIndex;
View view = daysPager.findViewWithTag(selectedPageIndex);
selectDay(view.findViewById(DAY_TV_RES_ID[dayIndex]),dayIndex);
}
}
private Runnable selectDayRunnable = new Runnable() {
@Override
public void run() {
setSelectedDay(selectedDayIndex);
}
};
}
date_tab_indicator.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="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/mon_to_sun_lay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/mon_fixed_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_weight="1"
android:gravity="center"
android:text="M" />
<TextView
android:id="@+id/tue_fixed_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_weight="1"
android:gravity="center"
android:text="T" />
<TextView
android:id="@+id/wed_fixed_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_weight="1"
android:gravity="center"
android:text="W" />
<TextView
android:id="@+id/thu_fixed_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_weight="1"
android:gravity="center"
android:text="T" />
<TextView
android:id="@+id/fri_fixed_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_weight="1"
android:gravity="center"
android:text="F" />
<TextView
android:id="@+id/sat_fixed_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_weight="1"
android:gravity="center"
android:text="S" />
<TextView
android:id="@+id/sun_fixed_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_weight="1"
android:gravity="center"
android:text="S" />
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/days_pager"
android:layout_width="match_parent"
android:layout_height="50dp" />
<View
android:id="@+id/line_indicator"
android:layout_width="15dp"
android:layout_height="3dp"
android:padding="5dp"
android:background="#000000"
/>
</LinearLayout>
days_pager_item.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:gravity="center"
android:orientation="horizontal">
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/day_mon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/day_circle_bg"
android:gravity="center"
android:layout_gravity="center"
android:textColor="@color/day_color_selector" />
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/day_tue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/day_circle_bg"
android:gravity="center"
android:layout_gravity="center"
android:textColor="@color/day_color_selector" />
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/day_wed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/day_circle_bg"
android:gravity="center"
android:layout_gravity="center"
android:textColor="@color/day_color_selector" />
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/day_thu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/day_circle_bg"
android:gravity="center"
android:layout_gravity="center"
android:textColor="@color/day_color_selector" />
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/day_fri"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/day_circle_bg"
android:gravity="center"
android:layout_gravity="center"
android:textColor="@color/day_color_selector" />
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/day_sat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/day_circle_bg"
android:gravity="center"
android:layout_gravity="center"
android:textColor="@color/day_color_selector" />
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/day_sun"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/day_circle_bg"
android:gravity="center"
android:layout_gravity="center"
android:textColor="@color/day_color_selector" />
</FrameLayout>
</LinearLayout>
days_color_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#000000"></item>
<item android:state_selected="false" android:color="#bdbebd"></item>
</selector>
days_circle_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="40dp"
android:height="40dp" />
<stroke android:width="1dp"
android:color="#bdbebd"
/>
</shape>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private DateTabIndicator dateTabIndicator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dateTabIndicator = findViewById(R.id.date_tab_indicator);
dateTabIndicator.setDays(Arrays.asList(new Integer[]{0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}));
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<com.karacken.datetabindicator.DateTabIndicator
android:id="@+id/date_tab_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
/>
</RelativeLayout>
输出:
答案 1 :(得分:0)
How to build a Horizontal ListView with RecyclerView? 检查“ Suragch”的答案,以及该答案的补充内容
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
//use your entire xml code here plus place a image view as
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below = "id of the date circle"
android:background = "add a line of length according to your requirement in drawables and assign here"
android:visibility="set to invisible"/>
/RelativeLayout>
然后在onClick()
类内部的ViewHolder
方法内部,通过调用imageView.setVisibility(View.VISIBLE)
和调用notifyDataSetChanged()
希望这对您有帮助...
答案 2 :(得分:0)
您可以通过触发RecycleView项目选择的更改来更改指示器位置。对于所选项目的更改,可以使用变量将所选位置保留在适配器中。当用户猛扑RecycleView时,请使用根据指示器的位置计算所选位置。