先给大家展示下效果图:
实现代码如下:
下面简单说下实现原理。
代码如下 | 复制代码 |
publicclassIndexBarextendsLinearLayoutimplementsView.OnTouchListener { privatestaticfinalString[] INDEXES =newString[]{"#","A","B","C","D","E","F","G","H", "I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}; privatestaticfinalintTOUCHED_BACKGROUND_COLOR =0x40000000; privateOnIndexChangedListener mListener; publicvoidsetOnIndexChangedListener(OnIndexChangedListener listener) { mListener = listener; } publicIndexBar(Context context) { this(context,null); } publicIndexBar(Context context, AttributeSet attrs) { this(context, attrs,0); } publicIndexBar(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } privatevoidinit(AttributeSet attrs) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.IndexBar); floatindexTextSize = ta.getDimension(R.styleable.IndexBar_indexTextSize, Utils.sp2px(getContext(),12)); intindexTextColor = ta.getColor(R.styleable.IndexBar_indexTextColor,0xFF616161); ta.recycle(); setOrientation(VERTICAL); setOnTouchListener(this); for(String index : INDEXES) { TextView text =newTextView(getContext()); text.setText(index); text.setTextSize(TypedValue.COMPLEX_UNIT_PX, indexTextSize); text.setTextColor(indexTextColor); text.setGravity(Gravity.CENTER); LinearLayout.LayoutParams params =newLinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,0,1); text.setLayoutParams(params); addView(text); } } @Override publicbooleanonTouch(View v, MotionEvent event) { switch(event.getAction()) { caseMotionEvent.ACTION_DOWN: setBackgroundColor(TOUCHED_BACKGROUND_COLOR); handle(v, event); returntrue; caseMotionEvent.ACTION_MOVE: handle(v, event); returntrue; caseMotionEvent.ACTION_UP: setBackgroundColor(Color.TRANSPARENT); handle(v, event); returntrue; } returnsuper.onTouchEvent(event); } privatevoidhandle(View v, MotionEvent event) { inty = (int) event.getY(); intheight = v.getHeight(); intposition = INDEXES.length * y / height; if(position<0) { position =0; }elseif(position >= INDEXES.length) { position = INDEXES.length -1; } String index = INDEXES[position]; booleanshowIndicator = event.getAction() != MotionEvent.ACTION_UP; if(mListener !=null) { mListener.onIndexChanged(index, showIndicator); } } publicinterfaceOnIndexChangedListener { voidonIndexChanged(String index,booleanshowIndicator); } } |
使用
代码如下 | 复制代码 |
publicclassCompanyActivityextendsBaseActivityimplementsIndexBar.OnIndexChangedListener { @Bind(R.id.lv_company) ListView lvCompany; @Bind(R.id.ib_indicator) IndexBar ibIndicator; @Bind(R.id.tv_indicator) TextView tvIndicator; privateList @Override protectedvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_company); // ... } @Override publicvoidonIndexChanged(String index,booleanshowIndicator) { intposition = -1; for(CompanyEntity company : mCompanyList) { if(TextUtils.equals(company.getName(), index)) { position = mCompanyList.indexOf(company); break; } } if(position != -1) { lvCompany.setSelection(position); } tvIndicator.setText(index); tvIndicator.setVisibility(showIndicator ? View.VISIBLE : View.GONE); } } |
继承自LinearLayout,添加了26个字母索引TextView,当手指滑动时通知Activity更新界面。
核心是OnTouchListener,手指滑动的时候根据当前Y坐标计算出手指所在的索引位置,要注意临界值。