没什么说的,就是一个代码整理。
先来看一下效果图:
标题少的:
标题多的:
因为最近两个项目都有类似效果,所以这里整理了一下代码。实现代码借鉴了 PagerSlidingTabStrip.
比较简单,所以这里就直接贴出了主要的实现代码:
public class HorizontalView extends HorizontalScrollView { private LinearLayout container; private int tabPadding = 8; private int tabTextSize = 16; private int tabSelTextSize = 16; private int tabTextColor; private int count; private int screenWidth; // 屏幕宽度 private int childViewWidth; // 控件宽度 private LinearLayout.LayoutParams matchParams, weightParmas; private List<String> strList; private int selPos = 0; private Context context; public interface onItemClickListener { void onClick(int position); } private onItemClickListener listener; // private static final int[] ATTRS = new int[]{ // android.R.attr.textSize, // android.R.attr.textColor // }; public HorizontalView(Context context, AttributeSet attrs) { super(context, attrs); /** *当你想让一个高度值不足scrollview的子控件fillparent的时候, * 单独的定义android:layout_height="fill_parent"是不起作用的, * 必须加上fillviewport属性,当子控件的高度值大于scrollview的高度时,这个标签就没有任何意义了。 */ setFillViewport(true); setHorizontalScrollBarEnabled(false); this.context = context; container = new LinearLayout(getContext()); container.setOrientation(LinearLayout.HORIZONTAL); container.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); addView(container); DisplayMetrics dm = getResources().getDisplayMetrics(); screenWidth = dm.widthPixels; int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); screenWidth = screenWidth - paddingLeft - paddingRight; // 把指定单位转换成像素。 tabPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm); tabTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm); tabSelTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabSelTextSize, dm); // get system attrs (android:textSize and android:textColor) // TypedArray a = context.obtainStyledAttributes(attrs, ATTRS); // // tabTextSize = a.getDimensionPixelSize(0, tabTextSize); // tabTextColor = a.getColor(1, tabTextColor); // // a.recycle(); matchParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT); weightParmas = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f); } public void setStrList(List<String> list) { strList = list; if (list == null || list.size() <= 0) { throw new IllegalStateException("There is no data in the title list "); } notifyDataSetChanged(); } public void setItemClickListener(onItemClickListener listener) { this.listener = listener; } public void notifyDataSetChanged() { container.removeAllViews(); count = strList.size(); childViewWidth = 0; for (int i = 0; i < count; i++) { addTextTab(i, strList.get(i)); } updateViewStyle(); } public void addTextTab(final int position, String title) { final HorizontalViewItem view = new HorizontalViewItem(context); view.setFocusable(true); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (childViewWidth > screenWidth) { int width = view.getWidth(); int left = view.getLeft(); // textview 左边位置 int tvMargin = screenWidth / 2 - width / 2; // TextView的目标位置 if (left < tvMargin) { scrollTo(0, 0); } else { scrollTo(left - tvMargin, 0); } } selPos = position; updateViewStyle(); if (listener != null) { listener.onClick(position); } // Log.i("lfq", "textView scroll x " + getScrollX() + ", getleft " + textView.getLeft() + " , getRight " + textView.getRight() + " , textView width " + textView.getWidth() + " , totalWidth : " + childViewWidth); } }); view.setPadding(tabPadding, 0, tabPadding, 0); view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // Log.i("lfq", position + " inside width : " + textView.getWidth()); childViewWidth += view.getWidth(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { getViewTreeObserver().removeGlobalOnLayoutListener( this); } else { getViewTreeObserver().removeOnGlobalLayoutListener( this); } } }); view.setText(title); // container.addView(view, position, weightParmas); container.addView(view); } public void updateViewStyle() { for (int i = 0; i < count; i++) { View v = container.getChildAt(i); if (v instanceof HorizontalViewItem) { HorizontalViewItem tab = (HorizontalViewItem) v; tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize); tab.setTypeface(null, Typeface.BOLD); tab.setTextColor(getResources().getColor(R.color.white_b0)); tab.setLineColor(getResources().getColor(R.color.c_ff7a7a)); // setAllCaps() is only available from API 14, so the upper case is made manually if we are on a // pre-ICS-build if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { tab.setAllCaps(true); } else { tab.setText(tab.getText().toString()); } if (selPos == i) { tab.setTextColor(Color.WHITE); tab.setLineColor(Color.WHITE); tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabSelTextSize); } } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int myWidth = getMeasuredWidth(); int childWidth = 0; for (int i = 0; i < count; i++) { childWidth += container.getChildAt(i).getMeasuredWidth(); } if (childWidth > 0 && myWidth > 0) { LinearLayout.LayoutParams params; if (childWidth <= myWidth) { params = weightParmas; } else { params = matchParams; } for (int i = 0; i < count; i++) { container.getChildAt(i).setLayoutParams(params); } } } }
HorizontalViewItem 是一个通过布局文件自定义的 View , 就是标题里面所需的一个文本,一条线。
<?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="vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxLines="1" android:textColor="#b0ffffff" android:textSize="14sp"/> <TextView android:id="@+id/tv_tip" android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="1dp" android:background="@android:color/white"/> </LinearLayout> </LinearLayout>
代码也就这些,没什么技术含量,便于以后再次使用,所以在这里整理一份。