android 汉字字母排序,android recycleView自定义字母检索A-Z排序滑动通讯录汉字英文相互转换...

b8dd6b73a2c1

image

核心类:

package com.example.test29api.slider_contact

import android.content.Context

import android.graphics.Canvas

import android.graphics.Color

import android.graphics.Paint

import android.graphics.Rect

import android.graphics.drawable.Drawable

import android.text.TextPaint

import android.text.TextUtils

import android.util.ArrayMap

import android.util.AttributeSet

import android.util.TypedValue

import android.view.MotionEvent

import android.view.View

import androidx.annotation.VisibleForTesting

import com.example.test29api.R

import java.util.*

import java.util.Collections.sort as sort1

class NewSideBar @JvmOverloads constructor(

context: Context,

attrs: AttributeSet? = null,

defStyleAttr: Int = 0

) : View(context, attrs, defStyleAttr) {

var indexes: Array = arrayOf(

"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", "#"

)

private val normalTextColor //未选中字体颜色

: Int

private val selectedTextColor //选中字体颜色

: Int

private val selectedBackground //选中背景色

: Drawable?

private var selectedIndex = 0

private val indexPaint: TextPaint

private val indexBounds //索引大小

: Rect

private val backGroundBound //背景绘制区域

: Rect

private var listener: OnSelectIndexChangedListener? = null

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

val widthMode = MeasureSpec.getMode(widthMeasureSpec)

val heightMode = MeasureSpec.getMode(heightMeasureSpec)

val sizeWidth = MeasureSpec.getSize(widthMeasureSpec)

val sizeHeight = MeasureSpec.getSize(heightMeasureSpec)

val wrapHeight =

indexes.size * (indexBounds.height() + indexBounds.height() / 2) + indexBounds.height() / 2

val warpWidth = indexBounds.width() * 2

setMeasuredDimension(

if (widthMode == MeasureSpec.EXACTLY) sizeWidth else warpWidth

, if (heightMode == MeasureSpec.EXACTLY) sizeHeight else wrapHeight

)

}

override fun onDraw(canvas: Canvas) {

indexBounds.offsetTo(indexBounds.width() / 2, indexBounds.height() / 2)

backGroundBound.offsetTo(indexBounds.width() / 4, indexBounds.height() / 4)

for (i in indexes.indices) {

if (selectedIndex == i) { //绘制index背景

if (selectedBackground != null) {

selectedBackground.bounds = backGroundBound

selectedBackground.draw(canvas)

}

indexPaint.color = selectedTextColor

} else {

indexPaint.color = normalTextColor

}

indexes[i]?.let {

canvas.drawText(

it,

indexBounds.left + indexBounds.width() / 2.toFloat(),

indexBounds.top + baseLineOffset.toFloat(),

indexPaint

)

}

indexBounds.offset(0, 3 * indexBounds.height() / 2)

backGroundBound.offset(0, 3 * indexBounds.height() / 2)

}

}

override fun dispatchTouchEvent(event: MotionEvent): Boolean {

var selectedIndex = getSelectedIndex(event.y)

if (selectedIndex < 0) {

selectedIndex = 0

}

if (selectedIndex >= indexes.size) {

selectedIndex = indexes.size - 1

}

when (event.action) {

MotionEvent.ACTION_DOWN -> {

isHovered = true

if (listener != null && selectedIndex != -1 && selectedIndex != this.selectedIndex) {

this.selectedIndex = selectedIndex

listener!!.onIndexHovered(indexes[selectedIndex])

}

invalidate()

}

MotionEvent.ACTION_MOVE -> {

if (listener != null && selectedIndex != -1 && selectedIndex != this.selectedIndex) {

this.selectedIndex = selectedIndex

listener!!.onIndexHovered(indexes[selectedIndex])

}

invalidate()

}

MotionEvent.ACTION_UP -> {

isHovered = false

if (listener != null && selectedIndex >= 0 && selectedIndex < indexes.size) {

this.selectedIndex = selectedIndex

listener!!.onIndexSelected(indexes[selectedIndex])

}

}

}

return true

}

private fun getSelectedIndex(pointY: Float): Int {

return ((pointY - indexBounds.height() / 4) / (indexBounds.height() * 3 / 2)).toInt()

}

private val baseLineOffset: Int

get() {

val fontMetrics = indexPaint.fontMetricsInt

val dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom

return indexBounds.height() / 2 + dy

}

fun setListener(listener: OnSelectIndexChangedListener?) {

this.listener = listener

}

fun setSections(sections: Array) {

indexes = sections

requestLayout()

}

fun setSelectedIndex(selectedIndex: String?) {

if (isHovered) {

return

}

for (i in indexes.indices) {

val index = indexes[i]

if (TextUtils.equals(selectedIndex, index)) {

this.selectedIndex = i

invalidate()

break

}

}

}

@VisibleForTesting

fun getSelectedIndex(): String? {

return if (selectedIndex >= 0 && selectedIndex < indexes.size) indexes[selectedIndex] else null

}

interface OnSelectIndexChangedListener {

fun onIndexHovered(index: String?)

fun onIndexSelected(index: String?)

}

interface SectionIndexer {

val sections: Array

fun getPositionForSection(section: T): Int

fun getSectionForPosition(position: Int): T

}

class PinyinSectionIndexer :

SectionIndexer {

private var indexables: MutableList>? = null

private var mapSections: ArrayMap, String>? = null

private var skipCount = 0

fun > handleIndexableList(indexableList: MutableList): List {

return handleIndexableList(indexableList, 0)

}

/**

* @param indexableList 数据源

* @param skipCount 1-置顶第一个item不参与abc...排序

* 0-全部参与abc...排序

*/

fun > handleIndexableList(

indexableList: MutableList,

skipCount: Int

): List {

if (mapSections == null) {

mapSections = ArrayMap()

}

mapSections!!.clear()

if (indexables == null) {

indexables = ArrayList()

}

indexables!!.clear()

this.skipCount = skipCount

if (indexableList.size == 0 || indexableList.size < skipCount) {

return indexableList

}

val sortList: List =

ArrayList(indexableList.subList(skipCount, indexableList.size)).also {

//通过拼音首字母排序

it.sortWith(Comparator { o1, o2 ->

var index1 = getSection(o1)

if (TextUtils.equals(index1, "#")) {

index1 = "a"

}

var index2 = getSection(o2)

if (TextUtils.equals(index2, "#")) {

index2 = "a"

}

index1!!.compareTo(index2!!)

})

}

indexables!!.addAll(sortList)

val dest: MutableList = indexableList.subList(0, skipCount)

dest.addAll(sortList)

return dest

}

/**

* @return 返回数据源所有拼音首字母String[]集合

*/

override

val sections: Array

get() {

val sections =

ArrayList()

var i = 0

val len = indexables!!.size

while (i < len) {

val section = getSection(indexables!![i])

if (!sections.contains(section)) {

sections.add(section)

}

i++

}

return sections.toTypedArray()

}

/**

* @return 返回首字母对应数据的第一个position

*/

override fun getPositionForSection(section: String?): Int {

var i = 0

val len = indexables!!.size

while (i < len) {

if (TextUtils.equals(section, getSection(indexables!![i]))) {

return i + skipCount

}

i++

}

return -1

}

/**

* @return 通过数据的position返回首字母

*/

override fun getSectionForPosition(position: Int): String? {

return if (indexables != null && position >= 0 && position < indexables!!.size) {

getSection(indexables!![Math.max(position - skipCount, 0)])

} else {

""

}

}

/**

* @return 获取indexable.getIndexable()的拼音大写首字母(空则返回#),同时更新#sections

*/

fun getSection(indexable: Indexable): String? {

var section = mapSections!![indexable]

if (TextUtils.isEmpty(section)) {

val indexableString = indexable.indexable

val instance = CharacterParser.instance

if (TextUtils.isEmpty(indexableString)) {

section = "#"

} else { //获取首字的拼音

val c = instance.convert(indexableString.substring(0, 1))

//首字母转大写

section =

if (TextUtils.isEmpty(c)) "0" else c?.substring(0, 1)?.toUpperCase(

Locale.ROOT

)

if (!section.isNullOrEmpty() && (section[0] < 'A' || section[0] > 'Z')) {

section = "#"

}

}

mapSections!![indexable] = section

}

return section

}

}

interface Indexable {

val indexable: T

}

init {

val ta = context.obtainStyledAttributes(attrs, R.styleable.NewSideBar)

normalTextColor =

ta.getColor(R.styleable.NewSideBar_normalTextColor, Color.GRAY)

selectedTextColor =

ta.getColor(R.styleable.NewSideBar_selectedTextColor, Color.BLACK)

selectedBackground = ta.getDrawable(R.styleable.NewSideBar_selectedBackground)

val textSize = ta.getDimension(

R.styleable.NewSideBar_indexTextSize, TypedValue

.applyDimension(

TypedValue.COMPLEX_UNIT_SP, 12f,

resources.displayMetrics

)

)

ta.recycle()

indexBounds = Rect()

indexPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)

indexPaint.textSize = textSize

indexPaint.textAlign = Paint.Align.CENTER

indexPaint.getTextBounds("W", 0, 1, indexBounds)

val larger = Math.max(indexBounds.width(), indexBounds.height())

indexBounds[0, 0, larger] = larger

backGroundBound = Rect(

0,

0,

indexBounds.right + indexBounds.right / 2,

indexBounds.bottom + indexBounds.bottom / 2

)

}

}

attrs:

以上类基本逻辑为:通过传入数据绘制字母及其背景,再通过接口和recycleView联动;

调用方式:

activity:

import android.os.Bundle

import android.util.Log

import android.view.View

import android.view.ViewGroup

import androidx.appcompat.app.AppCompatActivity

import androidx.recyclerview.widget.LinearLayoutManager

import androidx.recyclerview.widget.RecyclerView

import androidx.recyclerview.widget.RecyclerView.Adapter

import com.example.test29api.R

import kotlinx.android.extensions.LayoutContainer

import kotlinx.android.synthetic.main.activity_contact_slider.*

import kotlinx.android.synthetic.main.item_base.view.*

import kotlinx.coroutines.*

class ContactSliderActivity : AppCompatActivity() {

private val indexer by lazy {

NewSideBar.PinyinSectionIndexer()

}

private val testContactBeans by lazy {

mutableListOf(

TestContactBean("张三", "18888888888"),

TestContactBean("李四", "19999999999"),

TestContactBean("王五", "13333333333"),

TestContactBean("科比", "13444444444"),

TestContactBean("布鲁斯", "18213333333"),

TestContactBean("朱厚照", "18888888888"),

TestContactBean("朱祐樘", "17777777777"),

TestContactBean("朱高炽", "18888888888"),

TestContactBean("唐寅", "18888888855"),

TestContactBean("朱厚聪", "18888888866"),

TestContactBean("朱载厚", "18888888877"),

TestContactBean("刘瑾", "18215333333"),

TestContactBean("Alibaba", "15775757575"),

TestContactBean("Bruce", "15775757575"),

TestContactBean("富兰克林", "18215333333")

)

}

open class DefaultViewHolder(override val containerView: View) :

RecyclerView.ViewHolder(containerView), LayoutContainer

private val defaultAdapter by lazy {

object : Adapter() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DefaultViewHolder {

return DefaultViewHolder(

layoutInflater.inflate(

R.layout.item_base,

parent,

false

)

)

}

override fun getItemCount(): Int {

return testContactBeans.size

}

override fun onBindViewHolder(holder: DefaultViewHolder, position: Int) {

holder.itemView.run {

txtName.text = testContactBeans[position].name

txtPhone.text = testContactBeans[position].phone

}

}

}

}

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_contact_slider)

initView()

}

private fun initView() {

recyclerView.apply {

layoutManager = LinearLayoutManager(this@ContactSliderActivity)

adapter = defaultAdapter

addOnScrollListener(object : RecyclerView.OnScrollListener() {

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {

val position =

(recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()

if (defaultAdapter.itemCount != 0 && position in 0 until testContactBeans.size) {

sideBar.setSelectedIndex(indexer.getSectionForPosition(position))

}

}

})

}

sideBar.apply {

visibility = View.GONE

setListener(object : NewSideBar.OnSelectIndexChangedListener {

override fun onIndexHovered(index: String?) {

(recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(

indexer.getPositionForSection(index),

0

)

}

override fun onIndexSelected(index: String?) {

val manager = recyclerView.layoutManager as LinearLayoutManager

if (manager.findLastVisibleItemPosition() == (recyclerView.adapter?.itemCount

?: 0) - 1

) {

sideBar.setSelectedIndex(indexer.getSectionForPosition(manager.findFirstVisibleItemPosition()))

}

}

})

}

//设置排序后的数据源

val mutableListOf = mutableListOf()

mutableListOf.addAll(testContactBeans)

indexer.handleIndexableList(mutableListOf, 0).let { list ->

defaultAdapter.notifyItemRangeRemoved(0, testContactBeans.size - 1)

testContactBeans.clear()

testContactBeans.addAll(list)

defaultAdapter.notifyItemRangeChanged(0, testContactBeans.size - 1)

}

sideBar.setSections(indexer.sections)

sideBar.visibility = View.VISIBLE

}

}

activity_contact_slider:

android:layout_width="match_parent"

android:layout_height="match_parent"

xmlns:app="http://schemas.android.com/apk/res-auto">

android:id="@+id/recyclerView"

android:layout_width="0dp"

android:layout_height="0dp"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toTopOf="parent"

/>

android:id="@+id/sideBar"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginEnd="8dp"

app:indexTextSize="12sp"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintTop_toTopOf="parent"

app:normalTextColor="@android:color/darker_gray"

app:selectedBackground="@drawable/side_bar_choose_background"

app:selectedTextColor="@android:color/white" />

side_bar_choose_background:

android:shape="oval">

item_base:

android:layout_width="match_parent"

android:layout_height="70dp"

android:background="@android:color/white"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools">

android:id="@+id/txtName"

android:layout_width="0dp"

android:layout_height="48dp"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toTopOf="parent"

app:layout_constraintEnd_toStartOf="@id/txtPhone"

app:layout_constraintVertical_chainStyle="packed"

android:layout_marginStart="16dp"

android:layout_marginEnd="14dp"

android:textSize="16sp"

tools:text="项目成员"

android:gravity="center_vertical"

android:singleLine="true"/>

android:id="@+id/txtPhone"

android:layout_width="0dp"

android:layout_height="wrap_content"

app:layout_constraintStart_toEndOf="@id/txtName"

app:layout_constraintBottom_toBottomOf="@id/txtName"

app:layout_constraintTop_toTopOf="@id/txtName"

app:layout_constraintEnd_toEndOf="parent"

android:layout_marginStart="16dp"

android:layout_marginTop="8dp"

android:layout_marginEnd="14dp"

tools:text="1888888888"

android:singleLine="true"/>

CharacterParser

package com.example.test29api.slider_contact

/**

* Created by PengCangXu on 2017/5/7.

*/

class CharacterParser {

private var buffer: StringBuilder? = null

var resource: String? = null

/**

* 汉字转成ASCII码 * * @param chs * @return

*/

private fun getChsAscii(chs: String): Int {

var asc = 0

try {

val bytes = chs.toByteArray(charset("gb2312"))

if (bytes.size > 2 || bytes.size <= 0) {

throw RuntimeException("illegal resource string")

}

if (bytes.size == 1) {

asc = bytes[0].toInt()

}

if (bytes.size == 2) {

val hightByte = 256 + bytes[0]

val lowByte = 256 + bytes[1]

asc = 256 * hightByte + lowByte - 256 * 256

}

} catch (e: Exception) {

println("ERROR:ChineseSpelling.class-getChsAscii(String chs)$e")

}

return asc

}

/**

* 单字解析 * * @param str * @return

*/

fun convert(str: String): String? {

var result: String? = null

val ascii = getChsAscii(str)

if (ascii in 1..159) {

result = ascii.toString()

} else {

for (i in pyvalue.size - 1 downTo 0) {

if (pyvalue[i] <= ascii) {

result = pystr[i]

break

}

}

}

return result

}

/***词组解析 * * @param chs * @return */

fun parse(chs: String?): String {

var key: String

var value: String?

buffer = StringBuilder()

for (i in chs!!.indices) {

key = chs.substring(i, i + 1)

if (key.toByteArray().size >= 2) {

value = convert(key)

if (value == null) {

value = "unknown"

}

} else {

value = key

}

buffer!!.append(value)

}

return buffer.toString()

}

val spelling: String

get() = parse(resource)

companion object {

private val pyvalue = intArrayOf(

-20319,

-20317,

-20304,

-20295,

-20292,

-20283,

-20265,

-20257,

-20242,

-20230,

-20051,

-20036,

-20032,

-20026,

-20002,

-19990,

-19986,

-19982,

-19976,

-19805,

-19784,

-19775,

-19774,

-19763,

-19756,

-19751,

-19746,

-19741,

-19739,

-19728,

-19725,

-19715,

-19540,

-19531,

-19525,

-19515,

-19500,

-19484,

-19479,

-19467,

-19289,

-19288,

-19281,

-19275,

-19270,

-19263,

-19261,

-19249,

-19243,

-19242,

-19238,

-19235,

-19227,

-19224,

-19218,

-19212,

-19038,

-19023,

-19018,

-19006,

-19003,

-18996,

-18977,

-18961,

-18952,

-18783,

-18774,

-18773,

-18763,

-18756,

-18741,

-18735,

-18731,

-18722,

-18710,

-18697,

-18696,

-18526,

-18518,

-18501,

-18490,

-18478,

-18463,

-18448,

-18447,

-18446,

-18239,

-18237,

-18231,

-18220,

-18211,

-18201,

-18184,

-18183,

-18181,

-18012,

-17997,

-17988,

-17970,

-17964,

-17961,

-17950,

-17947,

-17931,

-17928,

-17922,

-17759,

-17752,

-17733,

-17730,

-17721,

-17703,

-17701,

-17697,

-17692,

-17683,

-17676,

-17496,

-17487,

-17482,

-17468,

-17454,

-17433,

-17427,

-17417,

-17202,

-17185,

-16983,

-16970,

-16942,

-16915,

-16733,

-16708,

-16706,

-16689,

-16664,

-16657,

-16647,

-16474,

-16470,

-16465,

-16459,

-16452,

-16448,

-16433,

-16429,

-16427,

-16423,

-16419,

-16412,

-16407,

-16403,

-16401,

-16393,

-16220,

-16216,

-16212,

-16205,

-16202,

-16187,

-16180,

-16171,

-16169,

-16158,

-16155,

-15959,

-15958,

-15944,

-15933,

-15920,

-15915,

-15903,

-15889,

-15878,

-15707,

-15701,

-15681,

-15667,

-15661,

-15659,

-15652,

-15640,

-15631,

-15625,

-15454,

-15448,

-15436,

-15435,

-15419,

-15416,

-15408,

-15394,

-15385,

-15377,

-15375,

-15369,

-15363,

-15362,

-15183,

-15180,

-15165,

-15158,

-15153,

-15150,

-15149,

-15144,

-15143,

-15141,

-15140,

-15139,

-15128,

-15121,

-15119,

-15117,

-15110,

-15109,

-14941,

-14937,

-14933,

-14930,

-14929,

-14928,

-14926,

-14922,

-14921,

-14914,

-14908,

-14902,

-14894,

-14889,

-14882,

-14873,

-14871,

-14857,

-14678,

-14674,

-14670,

-14668,

-14663,

-14654,

-14645,

-14630,

-14594,

-14429,

-14407,

-14399,

-14384,

-14379,

-14368,

-14355,

-14353,

-14345,

-14170,

-14159,

-14151,

-14149,

-14145,

-14140,

-14137,

-14135,

-14125,

-14123,

-14122,

-14112,

-14109,

-14099,

-14097,

-14094,

-14092,

-14090,

-14087,

-14083,

-13917,

-13914,

-13910,

-13907,

-13906,

-13905,

-13896,

-13894,

-13878,

-13870,

-13859,

-13847,

-13831,

-13658,

-13611,

-13601,

-13406,

-13404,

-13400,

-13398,

-13395,

-13391,

-13387,

-13383,

-13367,

-13359,

-13356,

-13343,

-13340,

-13329,

-13326,

-13318,

-13147,

-13138,

-13120,

-13107,

-13096,

-13095,

-13091,

-13076,

-13068,

-13063,

-13060,

-12888,

-12875,

-12871,

-12860,

-12858,

-12852,

-12849,

-12838,

-12831,

-12829,

-12812,

-12802,

-12607,

-12597,

-12594,

-12585,

-12556,

-12359,

-12346,

-12320,

-12300,

-12120,

-12099,

-12089,

-12074,

-12067,

-12058,

-12039,

-11867,

-11861,

-11847,

-11831,

-11798,

-11781,

-11604,

-11589,

-11536,

-11358,

-11340,

-11339,

-11324,

-11303,

-11097,

-11077,

-11067,

-11055,

-11052,

-11045,

-11041,

-11038,

-11024,

-11020,

-11019,

-11018,

-11014,

-10838,

-10832,

-10815,

-10800,

-10790,

-10780,

-10764,

-10587,

-10544,

-10533,

-10519,

-10331,

-10329,

-10328,

-10322,

-10315,

-10309,

-10307,

-10296,

-10281,

-10274,

-10270,

-10262,

-10260,

-10256,

-10254

)

var pystr = arrayOf(

"a",

"ai",

"an",

"ang",

"ao",

"ba",

"bai",

"ban",

"bang",

"bao",

"bei",

"ben",

"beng",

"bi",

"bian",

"biao",

"bie",

"bin",

"bing",

"bo",

"bu",

"ca",

"cai",

"can",

"cang",

"cao",

"ce",

"ceng",

"cha",

"chai",

"chan",

"chang",

"chao",

"che",

"chen",

"cheng",

"chi",

"chong",

"chou",

"chu",

"chuai",

"chuan",

"chuang",

"chui",

"chun",

"chuo",

"ci",

"cong",

"cou",

"cu",

"cuan",

"cui",

"cun",

"cuo",

"da",

"dai",

"dan",

"dang",

"dao",

"de",

"deng",

"di",

"dian",

"diao",

"die",

"ding",

"diu",

"dong",

"dou",

"du",

"duan",

"dui",

"dun",

"duo",

"e",

"en",

"er",

"fa",

"fan",

"fang",

"fei",

"fen",

"feng",

"fo",

"fou",

"fu",

"ga",

"gai",

"gan",

"gang",

"gao",

"ge",

"gei",

"gen",

"geng",

"gong",

"gou",

"gu",

"gua",

"guai",

"guan",

"guang",

"gui",

"gun",

"guo",

"ha",

"hai",

"han",

"hang",

"hao",

"he",

"hei",

"hen",

"heng",

"hong",

"hou",

"hu",

"hua",

"huai",

"huan",

"huang",

"hui",

"hun",

"huo",

"ji",

"jia",

"jian",

"jiang",

"jiao",

"jie",

"jin",

"jing",

"jiong",

"jiu",

"ju",

"juan",

"jue",

"jun",

"ka",

"kai",

"kan",

"kang",

"kao",

"ke",

"ken",

"keng",

"kong",

"kou",

"ku",

"kua",

"kuai",

"kuan",

"kuang",

"kui",

"kun",

"kuo",

"la",

"lai",

"lan",

"lang",

"lao",

"le",

"lei",

"leng",

"li",

"lia",

"lian",

"liang",

"liao",

"lie",

"lin",

"ling",

"liu",

"long",

"lou",

"lu",

"lv",

"luan",

"lue",

"lun",

"luo",

"ma",

"mai",

"man",

"mang",

"mao",

"me",

"mei",

"men",

"meng",

"mi",

"mian",

"miao",

"mie",

"min",

"ming",

"miu",

"mo",

"mou",

"mu",

"na",

"nai",

"nan",

"nang",

"nao",

"ne",

"nei",

"nen",

"neng",

"ni",

"nian",

"niang",

"niao",

"nie",

"nin",

"ning",

"niu",

"nong",

"nu",

"nv",

"nuan",

"nue",

"nuo",

"o",

"ou",

"pa",

"pai",

"pan",

"pang",

"pao",

"pei",

"pen",

"peng",

"pi",

"pian",

"piao",

"pie",

"pin",

"ping",

"po",

"pu",

"qi",

"qia",

"qian",

"qiang",

"qiao",

"qie",

"qin",

"qing",

"qiong",

"qiu",

"qu",

"quan",

"que",

"qun",

"ran",

"rang",

"rao",

"re",

"ren",

"reng",

"ri",

"rong",

"rou",

"ru",

"ruan",

"rui",

"run",

"ruo",

"sa",

"sai",

"san",

"sang",

"sao",

"se",

"sen",

"seng",

"sha",

"shai",

"shan",

"shang",

"shao",

"she",

"shen",

"sheng",

"shi",

"shou",

"shu",

"shua",

"shuai",

"shuan",

"shuang",

"shui",

"shun",

"shuo",

"si",

"song",

"sou",

"su",

"suan",

"sui",

"sun",

"suo",

"ta",

"tai",

"tan",

"tang",

"tao",

"te",

"teng",

"ti",

"tian",

"tiao",

"tie",

"ting",

"tong",

"tou",

"tu",

"tuan",

"tui",

"tun",

"tuo",

"wa",

"wai",

"wan",

"wang",

"wei",

"wen",

"weng",

"wo",

"wu",

"xi",

"xia",

"xian",

"xiang",

"xiao",

"xie",

"xin",

"xing",

"xiong",

"xiu",

"xu",

"xuan",

"xue",

"xun",

"ya",

"yan",

"yang",

"yao",

"ye",

"yi",

"yin",

"ying",

"yo",

"yong",

"you",

"yu",

"yuan",

"yue",

"yun",

"za",

"zai",

"zan",

"zang",

"zao",

"ze",

"zei",

"zen",

"zeng",

"zha",

"zhai",

"zhan",

"zhang",

"zhao",

"zhe",

"zhen",

"zheng",

"zhi",

"zhong",

"zhou",

"zhu",

"zhua",

"zhuai",

"zhuan",

"zhuang",

"zhui",

"zhun",

"zhuo",

"zi",

"zong",

"zou",

"zu",

"zuan",

"zui",

"zun",

"zuo"

)

val instance = CharacterParser()

}

}

以上的类主要做一些汉字ascii转拼音的操作;

TestContactBean:

package com.example.test29api.slider_contact

class TestContactBean(val name: String = "", val phone: String = "") : NewSideBar.Indexable {

override val indexable: String

get() {

return name

}

}

这里不要忘了继承NewSideBar的Indexable接口,便于获取需要排序的词组;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值