本元件繼承 HorizontalScrollView,結合 RadioGroup 與指示器動畫,實現標籤點擊切換、ViewPager 滑動同步、指示器平滑移動、箭頭顯示隱藏等功能。
public class SyncHorizontalScrollView extends HorizontalScrollView {
private View view;
private ImageView leftImage, rightImage;
private int windowWidth;
private Activity mContext;
private RadioGroup rg_nav_content;
private ImageView iv_nav_indicator;
private LayoutInflater mInflater;
private int indicatorWidth; // 單個標籤寬度
private int currentIndicatorLeft; // 當前指示器左邊距
private ViewPager mViewPager; // 關聯的 ViewPager
// ... 建構子與初始化方法
}
public void setSomeParam(ViewPager mViewPager, ImageView leftImage,
ImageView rightImage, String[] tabTitle, int count, Activity context) {
this.mContext = context;
this.mViewPager = mViewPager;
mInflater = LayoutInflater.from(context);
this.view = mInflater.inflate(R.layout.sync_hsv_item, null);
this.addView(view);
// 計算螢幕寬度與標籤寬度
DisplayMetrics dm = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(dm);
windowWidth = dm.widthPixels;
indicatorWidth = windowWidth / count;
init(tabTitle);
this.invalidate();
}
private void initNavigationHSV(String[] tabTitle) {
rg_nav_content.removeAllViews();
for (int i = 0; i < tabTitle.length; i++) {
RadioButton rb = (RadioButton) mInflater.inflate(R.layout.nav_radiogroup_item, null);
rb.setId(i);
rb.setText(tabTitle[i]);
rb.setLayoutParams(new LayoutParams(indicatorWidth, LayoutParams.MATCH_PARENT));
rg_nav_content.addView(rb);
}
}
private void setListener() {
rg_nav_content.setOnCheckedChangeListener((group, checkedId) -> {
RadioButton rb = (RadioButton) rg_nav_content.getChildAt(checkedId);
if (rb != null) {
// 指示器平移動畫
TranslateAnimation animation = new TranslateAnimation(
currentIndicatorLeft, rb.getLeft(), 0f, 0f);
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(100);
animation.setFillAfter(true);
iv_nav_indicator.startAnimation(animation);
// 切換 ViewPager
mViewPager.setCurrentItem(checkedId);
currentIndicatorLeft = rb.getLeft();
// HSV 滾動跟隨
smoothScrollTo(
(checkedId > 1 ? rb.getLeft() : 0)
- rg_nav_content.getChildAt(2).getLeft(), 0);
}
});
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (view.getWidth() <= windowWidth) {
leftImage.setVisibility(View.GONE);
rightImage.setVisibility(View.GONE);
} else {
if (l == 0) { // 最左邊
leftImage.setVisibility(View.GONE);
rightImage.setVisibility(View.VISIBLE);
} else if (view.getWidth() - l == windowWidth) { // 最右邊
leftImage.setVisibility(View.VISIBLE);
rightImage.setVisibility(View.GONE);
} else { // 中間
leftImage.setVisibility(View.VISIBLE);
rightImage.setVisibility(View.VISIBLE);
}
}
}
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/rl_nav"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#5AB0EB">
<RadioGroup
android:id="@+id/rg_nav_content"
android:layout_width="fill_parent"
android:layout_height="38dip"
android:orientation="horizontal"
android:background="#F2F2F2" />
<ImageView
android:id="@+id/iv_nav_indicator"
android:layout_width="1dip"
android:layout_height="5dip"
android:layout_alignParentBottom="true"
android:background="#5AB0EB"
android:scaleType="matrix" />
</RelativeLayout>
</LinearLayout>
<RadioButton xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:background="#F2F2F2"
android:button="@null"
android:gravity="center"
android:textColor="@drawable/rb_blue_bg"
android:textSize="14.0dip" />
// Activity/Fragment 中
SyncHorizontalScrollView hsv = findViewById(R.id.sync_hsv);
ViewPager viewPager = findViewById(R.id.viewpager);
ImageView leftArrow = findViewById(R.id.left_arrow);
ImageView rightArrow = findViewById(R.id.right_arrow);
String[] titles = {"首頁", "發現", "消息", "我的"};
hsv.setSomeParam(viewPager, leftArrow, rightArrow, titles, 4, this);
TranslateAnimation,效能優於屬性動畫