<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android自定義實現(xiàn)A-Z列表功能

          共 12839字,需瀏覽 26分鐘

           ·

          2021-11-29 20:33

          項目中需要用到A-Z的列表,點擊字母可以滾動到列表中對應字母位置。


          先看下怎么使用:


          xml中:

                  android:id="@+id/siderbar_letters"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:siderQuickItemTypebgColor="#3F88FF"        app:sliderLetterColor="#808080"        app:sliderLetterWidth="12sp"        app:siderQuickItemTypeTextWidth="14sp"        app:siderQuickItemTypeTextColor="#FFFFFF"/>


          java中:

          public class MainActivity extends AppCompatActivity {    private String[] str = new String[]{"一","二","三","死","一","一","一","一",            "商店","一","重新","我","as","第","是","把","留",            "阿薩德","as","都是","一","一","商店","商店","發(fā)","一",            "一","阿薩德","一","商店",};

          @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); List list = new ArrayList<>(); for(int i=0;i ItemBeans itemBeans = new ItemBeans(); itemBeans.setType(i+1); itemBeans.setValues(str[i]); list.add(itemBeans); }
          SiderQuickBarView siderQuickBarView = findViewById(R.id.siderbar_letters); siderQuickBarView.setLetters(list) .setOnItemClickListener(letterBean -> Toast.makeText(this,"type==>"+letterBean.getType()+" value==>"+letterBean.getLetterName(),Toast.LENGTH_SHORT).show() ); }}


          自定義屬性:

                                                                                                         


          只需要把任意文字轉(zhuǎn)成list ,按規(guī)則傳入,即可自動按字母排序,點擊后可返回當前字母和字母對應的key值。


          效果圖:



          下面說一下實現(xiàn)的思路:


          ????1.控件由兩部分構(gòu)成:下面的RecyclerView和右側(cè)的自定義字母,使用的是幀布局。
          ????2.將輸入的文字按字母分類。
          ? ? 3.將分類好的字母放入新的list中,字母和字母對應的文字用type進行區(qū)分。
          ????4.為RecyclerView創(chuàng)建適配器,添加點擊事件。
          ????5.為字母添加點擊事件,并使RecyclerView滑動。
          ????6.封裝自定義屬性。


          好了,放一下主要代碼:

          public class SiderQuickBarView extends FrameLayout {    private RecyclerView rvLetter;    private SliderLetterView sliderLetterView;    private GuideBbar guideBbar;    private Context context;    private List letterBeans;    private List cityBeans;
          //自定義屬性 private int siderQuickItemTypebgColor; private int siderQuickItemTypeTvColor; private float siderQuickItemTypeTextWidth;
          private int sliderLetterColor; private int sliderLetterWidth;
          private OnItemClickListener onItemClickListener;
          public SiderQuickBarView(Context context) { super(context); initView(context); }

          public SiderQuickBarView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SiderQuickBarView); siderQuickItemTypebgColor = array.getColor(R.styleable.SiderQuickBarView_siderQuickItemTypebgColor, ContextCompat.getColor(context,R.color.colorAccent)); siderQuickItemTypeTvColor = array.getColor(R.styleable.SiderQuickBarView_siderQuickItemTypeTextColor,ContextCompat.getColor(context,R.color.whilte)); siderQuickItemTypeTextWidth = array.getDimensionPixelSize(R.styleable.SiderQuickBarView_siderQuickItemTypeTextWidth,20);
          sliderLetterColor = array.getColor(R.styleable.SiderQuickBarView_sliderLetterColor,ContextCompat.getColor(context,R.color.black)); sliderLetterWidth = array.getDimensionPixelSize(R.styleable.SiderQuickBarView_sliderLetterWidth,50); initView(context); array.recycle(); }
          private void initView(Context context) { this.context = context; //左邊列表 rvLetter = new RecyclerView(context); rvLetter.setLayoutManager(new LinearLayoutManager(context)); LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT); rvLetter.setLayoutParams(layoutParams);
          //右邊字母列表 sliderLetterView = new SliderLetterView(context,sliderLetterColor,sliderLetterWidth); LayoutParams layoutParams1 = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); layoutParams1.gravity = Gravity.END; layoutParams1.bottomMargin = 10; sliderLetterView.setLayoutParams(layoutParams1);
          //GuiBar guideBbar = new GuideBbar(context); FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams2.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; layoutParams2.bottomMargin = 100; guideBbar.setLayoutParams(layoutParams2);
          addView(rvLetter); addView(sliderLetterView);// addView(guideBbar); //字母監(jiān)聽 setListener(); }
          private void setListener() { sliderLetterView.setOnLetterTouchListener(letter -> { for(int i=0;i if(letter.equals(letterBeans.get(i).getLetterName())){ moveToPosition(i); break; } } Toast.makeText(context,letter,Toast.LENGTH_SHORT).show(); });
          rvLetter.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); double scrollY = recyclerView.computeVerticalScrollOffset(); double s = recyclerView.computeVerticalScrollExtent(); double sum = recyclerView.computeVerticalScrollRange()-s; double f = scrollY/sum; guideBbar.setGuideX(f); } });
          }
          private void moveToPosition(int position) { if (position != -1) { rvLetter.scrollToPosition(position); LinearLayoutManager mLayoutManager = (LinearLayoutManager) rvLetter.getLayoutManager(); assert mLayoutManager != null; mLayoutManager.scrollToPositionWithOffset(position, 0); } }
          public SiderQuickBarView setLetters(List letters){ Map> letterMap = letters.stream().collect(Collectors.groupingBy(letter -> PinYinUtils.getFirstLetter(letter.getValues()))); Iterator>> itLetter = letterMap.entrySet().iterator(); cityBeans = new ArrayList<>(); letterBeans = new ArrayList<>(); Iterator keySet = letterMap.keySet().iterator(); while (keySet.hasNext()){ CityBean cityBean = new CityBean(); cityBean.setKey(keySet.next()); cityBeans.add(cityBean); } //對字母排序 SiderComparator siderComparator = new SiderComparator(); Collections.sort(cityBeans,siderComparator);
          cityBeans.forEach(cityBean -> { List contentList = new ArrayList(); List itemBeans = letterMap.get(cityBean.getKey()); LetterBean letterBean = new LetterBean(); letterBean.setLetterType(LetterType.title); letterBean.setLetterName(cityBean.getKey()); contentList.add(letterBean); itemBeans.forEach(item -> { LetterBean letterBean1 = new LetterBean(); letterBean1.setLetterType(LetterType.contet); letterBean1.setType(item.getType()); letterBean1.setLetterName(item.getValues()); contentList.add(letterBean1); }); cityBean.setBeanList(contentList); });
          cityBeans.forEach(cityBean -> { letterBeans.addAll(cityBean.getBeanList()); }); LetterListAdapter letterListAdapter = new LetterListAdapter(context, letterBeans, siderQuickItemTypeTvColor, siderQuickItemTypebgColor, siderQuickItemTypeTextWidth); rvLetter.setAdapter(letterListAdapter); letterListAdapter.setOnItemClickListener((adapter, position) -> { LetterListAdapter la = (LetterListAdapter) adapter; LetterBean item = la.getItem(position); if(onItemClickListener != null){ onItemClickListener.onClick(item); }
          }); return this; }
          interface OnItemClickListener{ void onClick(LetterBean letterBean); }
          public SiderQuickBarView setOnItemClickListener(OnItemClickListener onItemClickListener){ this.onItemClickListener = onItemClickListener; return this; }

          class SiderComparator implements Comparator {
          @Override public int compare(CityBean cityBean1, CityBean cityBean2) { return cityBean1.getKey().compareTo(cityBean2.getKey()); } }

          @Retention(RetentionPolicy.SOURCE) @IntDef({LetterType.title,LetterType.contet}) public @interface LetterType{ int title = 0; int contet = 1; }}


          這個就是整個控件了,繼承自FrameLayout,包含一個RecyclerView和右邊的自定義字母(忽略被注釋的View)


          這里最主要的就是將輸入的字符串信息,按照字母分類,我這里用到了一個第三庫:

           implementation 'com.belerweb:pinyin4j:2.5.1'


          外加這個庫的一個工具類:

          public class PinYinUtils {    /**     * 將字符串中的中文轉(zhuǎn)化為拼音,其他字符不變     *     * @param inputString     * @return     */    public static String getPingYin(String inputString) {        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);        format.setVCharType(HanyuPinyinVCharType.WITH_V);
          char[] input = inputString.trim().toCharArray(); String output = ""; try { for (int i = 0; i < input.length; i++) { if (java.lang.Character.toString(input[i]).matches("[\\u4E00-\\u9FA5]+")) { String[] temp = PinyinHelper.toHanyuPinyinStringArray(input[i], format); output += temp[0]; } else { output += java.lang.Character.toString(input[i]); } } } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } return output; } /** * 獲取漢字串拼音首字母,英文字符不變 * @param chinese 漢字串 * @return 漢語拼音首字母 */ public static String getFirstSpell(String chinese) { StringBuffer pybf = new StringBuffer(); char[] arr = chinese.toCharArray(); HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); for (int i = 0; i < arr.length; i++) { if (arr[i] > 128) { try { String[] temp = PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat); if (temp != null) { pybf.append(temp[0].charAt(0)); } } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { pybf.append(arr[i]); } } return pybf.toString().replaceAll("\\W", "").trim(); } /** * 獲取漢字串拼音,英文字符不變 * @param chinese 漢字串 * @return 漢語拼音 */ public static String getFullSpell(String chinese) { StringBuffer pybf = new StringBuffer(); char[] arr = chinese.toCharArray(); HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); for (int i = 0; i < arr.length; i++) { if (arr[i] > 128) { try { pybf.append(PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat)[0]); } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { pybf.append(arr[i]); } } return pybf.toString(); }
          /** 獲取首字母 * @param letter * @return */ public static String getFirstLetter(String letter){ StringBuffer pybf = new StringBuffer(); char[] arr = letter.toCharArray(); HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); for (int i = 0; i < arr.length; i++) { if (arr[i] > 128) { try { pybf.append(PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat)[0]); } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { pybf.append(arr[i]); } } return pybf.substring(0,1); }}


          這個工具類的作用,可以將文字的首字母給取出來, 那么取出來干嘛呢??
          下面我正好借助lamda表達式,根據(jù)首字母將數(shù)據(jù)進行分組:

          Map> letterMap = letters.stream().collect(Collectors.groupingBy(letter -> PinYinUtils.getFirstLetter(letter.getValues())));


          分完組之后的數(shù)據(jù)就是一個map集合 map的key就是 各數(shù)據(jù)對應的首字母,value就是各首字母對應的數(shù)據(jù),再將map中的數(shù)據(jù),放入一個新的list中,所以現(xiàn)在混亂數(shù)據(jù)就變成了一組組有序集合了,但現(xiàn)在還不夠,因為是按照A-Z排序,目前不是按A-Z,可能是g,f,a,d 這樣亂排序的,只是把數(shù)據(jù)都放在了它們各自的首字母下面而已,那么,下面就借助Comparator這個接口讓字母按照A-Z的順序排序:

          class SiderComparator implements Comparator {
          @Override public int compare(CityBean cityBean1, CityBean cityBean2) { return cityBean1.getKey().compareTo(cityBean2.getKey()); } }
          //對字母排序 SiderComparator siderComparator = new SiderComparator(); Collections.sort(cityBeans,siderComparator);


          排序完成之后,這個list就可以像普通的list一樣放入RecyclerView的適配器中使用了。


          下面看一下自定義的字母:

          /** * 右邊字母自定義 * @author amggy */public class SliderLetterView extends View {    private Paint paint;    private String[] letters;    private double itemHeight;    private int position;    private OnLetterTouchListener onLetterTouchListener;
          private int paintColor; private int paintStrokWith;
          public SliderLetterView(Context context,int paintColor,int paintStrokWith) { super(context); this.paintColor = paintColor; this.paintStrokWith = paintStrokWith; initView(context); }
          public SliderLetterView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); initView(context);
          }
          public SliderLetterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); }
          private void initView(Context context) { letters = new String[]{"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"}; position = 0; paint = new Paint(); paint.setAntiAlias(true); paint.setDither(true); paint.setColor(paintColor); paint.setTextSize(paintStrokWith); paint.setTextAlign(Paint.Align.CENTER); }
          @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); double screenHeight = getHeight(); itemHeight = screenHeight /letters.length; float letterX = (float)getWidth()/2; for(int i=0;i canvas.drawText(letters[i],letterX,(float) ((i+1)*itemHeight),paint); } }
          @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: float eventY = event.getY(); position = (int) (eventY/itemHeight); if(onLetterTouchListener != null){ onLetterTouchListener.onTouch(letters[position]); } break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: break; default: break; } return true; }
          @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int with = MeasureSpec.getSize(widthMeasureSpec); int withMode = MeasureSpec.getMode(widthMeasureSpec);
          int high = MeasureSpec.getSize(heightMeasureSpec); int highMode = MeasureSpec.getMode(heightMeasureSpec);
          int w = 0; int h = 0;
          switch(withMode){ case MeasureSpec.EXACTLY: w = with; break; case MeasureSpec.AT_MOST: w = 80; break; default: break; }
          switch(highMode){ case MeasureSpec.EXACTLY: h = high; break; case MeasureSpec.AT_MOST: h = getMeasuredHeight(); break; default: break; } setMeasuredDimension(w,h); }

          public void setOnLetterTouchListener(OnLetterTouchListener onLetterTouchListener){ this.onLetterTouchListener = onLetterTouchListener; }
          public interface OnLetterTouchListener{ /** 返回選中字母 * @param letter 字母 */ void onTouch(String letter); }}

          自定義字母繼承自View,按照控件的高度,等分的繪制字母,添加onTouch事件,將觸碰到的字母返回出去,給RecyclerView滾動到指定位置做準備。

          瀏覽 58
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本精品在线播放 | 一级日韩在线观看 | 影音先锋av成人电影在线网址 | 免费视频一级内射 | 菲儿操逼视频播放 |