52.悬浮首字母指示器


1.示例代码:
数据的处理流程:
(1)获取服务器数据
(2)将数据源拼音化
(3)将数据源排序
(4)将数据源过滤掉大写字母
适配器的显示:
(1)长度为1就是索引字母,加载索引Item
(2)长度不为1就是数据源,加载数据源Item

这里有一个疑问:加载不同布局的时候,适配器的布局似乎不方便复用啊?怎么破?

视图的绘制流程:
(1)根据屏幕高度,动态设置索引视图的高度
(2)监听索引视图的手势事件

/*更多品牌*/
public class A4_BrandActivity extends MyBaseActivity {

private String[] indexStr;// 索引视图的数据
int height;// 索引视图的字体高度
private String data[];//汉字数组
private String pinyinData[];//拼音数组
HashMap<String, String> chineseMap = new HashMap<String, String>();// 拼音-汉字的键值对
HashMap<String, Integer> idMap = new HashMap<String, Integer>();// 拼音-id的键值对
String nData[] = new String[]{};// 数据源,整合了索引字母
private HashMap<String, Integer> selector;// 存放含有索引字母的位置
MyAdapter adapter;
List<Brand> brandList;
List<String> nameList;
List<String> tempData = new ArrayList<String>();

@InjectView(R.id.layout)
LinearLayout layoutIndex;//悬浮索引视图
@InjectView(R.id.tv)
TextView tv_show;//显示选中的字母
@InjectView(R.id.listView1)
ListView listView;

@OnClick(R.id.bt_back)
public void doBack(View view) {
finish();
}

@OnItemClick(R.id.listView1)
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
EventBus.getDefault().post(new MyBaseEvent(MyEventEnum.GetBrandCarList, new getBrandCarListEvent(idMap.get(nData[arg2]))));
finish();
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_morebrand);
loadData();
}

/**
* 根据屏幕高度,动态设置索引视图的高度
*/
public void onWindowFocusChanged(boolean hasFocus) {
// oncreate里面执行下面的代码没反应,因为oncreate里面得到的getHeight=0
System.out
.println("layoutIndex.getHeight()=" + layoutIndex.getHeight());
height = layoutIndex.getHeight() / indexStr.length;
getIndexView();
}

private void loadData() {
MyHttpControl.getBrandList(new H.HttpListener() {
@Override
public void onSuccess(String s) {
try {
getBrandListResponse response = JSON.parseObject(s, getBrandListResponse.class);
brandList = response.getBrandList();
nameList = new ArrayList<String>();
for (int i = 0; i < brandList.size(); i++) {
nameList.add(brandList.get(i).getBrandName());
}
data = (String[]) nameList.toArray(new String[brandList.size()]);


LogUtil.e("data=" + JSON.toJSONString(data));

dataToPinyin();

LogUtil.e("pinyinData=" + JSON.toJSONString(pinyinData));
LogUtil.e("chineseMap=" + chineseMap.toString());
LogUtil.e("idMap=" + idMap.toString());

dataToSort();
LogUtil.e("nData=" + JSON.toJSONString(nData));

dataToFilter();
LogUtil.e("nData02=" + JSON.toJSONString(nData));


adapter = new MyAdapter(A4_BrandActivity.this);
listView.setAdapter(adapter);
} catch (Exception e) {
LogUtil.e("e=" + e.getMessage());
}


}

@Override
public void onFailure(Throwable throwable, String s) {

}
});

indexStr = 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"};
}

/**
* 1.将数据源拼音化
*/
private void dataToPinyin() {
pinyinData = new String[data.length];
for (int i = 0; i < data.length; i++) {
String pinyin = converterToPinYin(data[i]);
pinyinData[i] = pinyin;
chineseMap.put(pinyin, data[i]);
idMap.put(pinyin, brandList.get(i).getBrandId());
}

}

/**
* 2.将数据源排序
*/
public void dataToSort() {
TreeSet<String> set = new TreeSet<String>();
// 获取初始化数据源中的首字母,添加到set
for (String string : pinyinData) {
set.add(String.valueOf(string.charAt(0)));
}
// 新数组的长度为原数据加上set的大小
nData = new String[pinyinData.length + set.size()];
int i = 0;
for (String string : set) {
nData[i] = string;
i++;
}
// 将原数据拷贝到新数据中
System.arraycopy(pinyinData, 0, nData, set.size(), pinyinData.length);
Arrays.sort(nData, String.CASE_INSENSITIVE_ORDER);// 自动按照首字母排序
}

/**
* 3.将数据源过滤掉大写字母
*/
private void dataToFilter() {
//过滤掉nData中的所有大写的拼音
for (int i = 0; i < nData.length; i++) {
if (nData[i].length() == 1) {
char t = nData[i].charAt(0);
if (t <= 'Z' && t >= 'A') {
} else {
tempData.add(nData[i]);
}
} else {
tempData.add(nData[i]);
}

}
LogUtil.e("tempData=" + tempData.toString());
nData = (String[]) tempData.toArray(new String[tempData.size()]);
}

/**
* 绘制索引列表
*/
public void getIndexView() {
LinearLayout.LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT, height);
// params.setMargins(10, 5, 10, 0);
for (int i = 0; i < indexStr.length; i++) {
final TextView tv = new TextView(this);
tv.setLayoutParams(params);
tv.setTextColor(0xffffffff);
tv.setText(indexStr[i]);
tv.setPadding(10, 0, 10, 0);
layoutIndex.addView(tv);
layoutIndex.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event)

{
float y = event.getY();
int index = (int) (y / height);
if (index > -1 && index < indexStr.length) {// 防止越界
String key = indexStr[index];
if (selector.containsKey(key)) {
int pos = selector.get(key);
if (listView.getHeaderViewsCount() > 0) {// 防止ListView有标题栏,本例中没有。
listView.setSelectionFromTop(
pos + listView.getHeaderViewsCount(), 0);
} else {
listView.setSelectionFromTop(pos, 0);// 滑动到第一项
}
tv_show.setVisibility(View.VISIBLE);
tv_show.setText(indexStr[index]);
}
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
layoutIndex.setBackgroundColor(Color
.parseColor("#232323"));
break;
case MotionEvent.ACTION_MOVE:

break;
case MotionEvent.ACTION_UP:
layoutIndex.setBackgroundColor(Color
.parseColor("#232323"));
tv_show.setVisibility(View.INVISIBLE);
break;
}
return true;
}
});
}
}

/**
* 汉语拼音转换工具
*/
public String converterToPinYin(String chinese) {
String pinyinString = "";
char[] charArray = chinese.toCharArray();
// 根据需要定制输出格式,我用默认的即可
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
try {
// 遍历数组,ASC码大于128进行转换
for (int i = 0; i < charArray.length; i++) {
if (charArray[i] > 128) {
// charAt(0)取出首字母
if (charArray[i] >= 0x4e00 && charArray[i] <= 0x9fa5) { // 判断是否中文
pinyinString += PinyinHelper.toHanyuPinyinStringArray(
charArray[i], defaultFormat)[0];
} else { // 不是中文的打上未知,所以无法处理韩文日本等等其他文字
pinyinString += "?";
}
} else {
pinyinString += charArray[i];
}
}
return pinyinString;
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
return null;
}
}

/**
* 自定义适配器
*/
private class MyAdapter extends BaseAdapter {
public MyAdapter(Context context) {
selector = new HashMap<String, Integer>();
for (int j = 0; j < indexStr.length; j++) {// 循环字母表,找出nData中对应字母的位置
for (int i = 0; i < nData.length; i++) {
if (nData[i].equals(indexStr[j].toLowerCase())) {
selector.put(indexStr[j], i);
}
}

}
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return nData.length;
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return nData[position];
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}

@Override
public boolean isEnabled(int position) {
// TODO Auto-generated method stub
if (nData[position].length() == 1)// 如果是字母索引
return false;// 表示不能点击
return super.isEnabled(position);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
String item = nData[position];
if (item.length() == 1) {
convertView = getLayoutInflater().inflate(R.layout.index, null);
TextView tv = (TextView) convertView
.findViewById(R.id.text_index);
tv.setText(item.toUpperCase());
} else {
convertView = getLayoutInflater().inflate(R.layout.item, null);
TextView tv = (TextView) convertView
.findViewById(R.id.text_brand);
tv.setText(chineseMap.get(item));// 显示的是拼音对应的汉字

ImageView iv = (ImageView) convertView
.findViewById(R.id.img_brand);
if (position % 3 == 0) {
iv.setBackgroundResource(R.drawable.homepage_car_logo_01);
} else if (position % 3 == 1) {
iv.setBackgroundResource(R.drawable.homepage_car_logo_02);
} else {
iv.setBackgroundResource(R.drawable.homepage_car_logo_03);
}

}
return convertView;
}
}

}
2.布局资源
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:clipToPadding="true"
android:fitsSystemWindows="true"
android:background="@color/yellow"
android:orientation="vertical">

<RelativeLayout
android:id="@+id/layout_head"
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/yellow">

<ImageView

android:id="@+id/bt_back"
android:layout_width="22dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:padding="5dp"
android:src="@drawable/back" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="更多品牌"
android:textSize="18dp" />
</RelativeLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#26353A">

<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#c3c3c3"
android:scrollbars="none"></ListView>

<TextView
android:id="@+id/tv"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:background="#f0606060"
android:gravity="center"
android:text="A"
android:textColor="#ffffff"
android:textSize="30sp"
android:visibility="invisible" />

<LinearLayout
android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="right|center_vertical"
android:layout_marginBottom="15dp"
android:layout_marginRight="5dp"
android:layout_marginTop="15dp"
android:background="@drawable/shape_index"
android:gravity="center"
android:orientation="vertical"></LinearLayout>
</FrameLayout>

</LinearLayout>
附件1:汉字转拼音需要用到的jar
pinyin4j-2.5.0.jar
附件2:这是我自己从服务器获取到的数据
data.txt





原文地址:https://www.cnblogs.com/yutianran/p/5069664.html