第一次写博客,也刚踏入工作,想着把自己在项目中遇到的问题,以及自己在工作中所做的项目记录下来,方便以后自己查找知识,一开始没有接触过Android,为了找工作,自学了5个月的Java,到公司实习的主要负责任务是安卓开发。
第一个做的任务就是做的手机通讯录,虽然做出来了,但是还是大多数借鉴网络上的,自己再做了一点修改。
下面是自己做的效果图,供大家参考,写的不好,大家就随便看看,希望对借鉴的人有点参考的意义。
上面几幅图形是运行成功候的图像,接下来就是代码部分。
package com.example.lastmodel;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageButton addUser;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addUser = findViewById(R.id.addUser);
addUser.setOnClickListener(this);
}
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,AddUserActivity.class));
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="联系人"
android:layout_centerHorizontal="true"
android:textSize="30dp"/>
<ImageButton
android:id="@+id/addUser"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="@drawable/add"/>
RelativeLayout>
package com.example.lastmodel;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class AddUserActivity extends AppCompatActivity implements View.OnClickListener {
private MyDatabaseHelper dbHelper;
private EditText username,telnumber;
private Button ok_add;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_user);
dbHelper = new MyDatabaseHelper(this,"Use.db",null,1);
username = findViewById(R.id.add_user_name);
telnumber = findViewById(R.id.add_user_telnumber);
ok_add = findViewById(R.id.ok_add);
ok_add.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.ok_add:{
String name = username.getText().toString();
String tel_number = telnumber.getText().toString();
if (name == null||tel_number == null){
Toast.makeText(this,"用户名和电话不能为空",Toast.LENGTH_SHORT).show();
}else {
SQLiteDatabase db = dbHelper.getReadableDatabase();
ContentValues values = new ContentValues();
values.put("name",name);
values.put("telnumber",tel_number);
db.insert("Use",null,values);
Toast.makeText(this,"添加成功",Toast.LENGTH_SHORT).show();
startActivity(new Intent(AddUserActivity.this,UserListViewActivity.class));
this.finish();
db.close();
}
}
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AddUserActivity">
<EditText
android:id="@+id/add_user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="姓名"/>
<EditText
android:id="@+id/add_user_telnumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_below="@+id/add_user_name"
android:hint="电话号码"/>
<Button
android:id="@+id/ok_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/add_user_telnumber"
android:text="添加"/>
RelativeLayout>
package com.example.lastmodel;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.widget.ListView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class UserListViewActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
private RecyclerView mRecyclerView;
private List<SortModel> SourceDateList;
private SideBar sideBar;
private TextView dialog;
private SortAdapter adapter;
private ClearEditText mClearEditText;
private PinyinComparator pinyinComparator;
LinearLayoutManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_list_view);
dbHelper = new MyDatabaseHelper(this,"User4.db",null,1);
initViews();
initUser();
mRecyclerView = findViewById(R.id.recyclerView);
SourceDateList = filledData(SourceDateList);
}
private void initViews() {
pinyinComparator = new PinyinComparator();
sideBar = findViewById(R.id.sideBar);
dialog = findViewById(R.id.dialog);
sideBar.setTextView(dialog);
sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {
@Override
public void onTouchingLetterChanged(String s) {
//该字母首次出现的位置
int position = adapter.getPositionForSection(s.charAt(0));
if (position != -1) {
manager.scrollToPositionWithOffset(position, 0);
}
}
});
mClearEditText = findViewById(R.id.filter_edit);
mClearEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
filterData(s.toString());
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
public List<SortModel> initUser(){
SourceDateList = new ArrayList<>();
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.query("Use",null,null,null,null,null,null);
if (cursor.moveToFirst()){
do{
String name = cursor.getString(cursor.getColumnIndex("name"));
SortModel data = new SortModel(name);
//SourceDateList.add(data);
SourceDateList.add(data);
}while (cursor.moveToNext());
}
cursor.close();
return SourceDateList;
}
private List<SortModel> filledData(List<SortModel> list) {
List<SortModel> mSortList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
SortModel sortModel = list.get(i);
//sortModel.setName(list.get(i));
//汉字转换成拼音
String pinyin = PinyinUtils.getPingYin(list.get(i).getName());
String sortString = pinyin.substring(0, 1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if (sortString.matches("[A-Z]")) {
sortModel.setLetters(sortString.toUpperCase());
} else {
sortModel.setLetters("#");
}
mSortList.add(sortModel);
}
return mSortList;
}
private void filterData(String filterStr) {
List<SortModel> filterDateList = new ArrayList<>();
if (TextUtils.isEmpty(filterStr)) {
filterDateList = SourceDateList;
} else {
filterDateList.clear();
for (SortModel sortModel : SourceDateList) {
String name = sortModel.getName();
if (name.indexOf(filterStr.toString()) != -1 ||
PinyinUtils.getFirstSpell(name).startsWith(filterStr.toString())
//不区分大小写
|| PinyinUtils.getFirstSpell(name).toLowerCase().startsWith(filterStr.toString())
|| PinyinUtils.getFirstSpell(name).toUpperCase().startsWith(filterStr.toString())
) {
filterDateList.add(sortModel);
}
}
}
// 根据a-z进行排序
Collections.sort(filterDateList, pinyinComparator);
adapter.updateList(filterDateList);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:focusable="true"
android:focusableInTouchMode="true">
<com.example.lastmodel.ClearEditText
android:id="@+id/filter_edit"
android:layout_width="match_parent"
android:layout_height="38dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="10dp"
android:layout_marginRight="12dp"
android:layout_marginBottom="5dp"
android:background="@drawable/shape"
android:drawableLeft="@drawable/drawable"
android:hint="搜索联系人"
android:maxLines="1"
android:paddingLeft="8dp"
android:textSize="17dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<TextView
android:id="@+id/dialog"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:background="#A9A9A9"
android:gravity="center"
android:textColor=" #000000"
android:textSize="30dp"
android:visibility="invisible" />
<com.example.lastmodel.SideBar
android:id="@+id/sideBar"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
/>
RelativeLayout>
LinearLayout>
以上的代码就是界面以及部分功能实现的代码,接下来的代码就是辅助类。
该类主要的功能是获得名字的首汉字,以及名字前面的圆形和随机分布圆形的颜色
package com.example.lastmodel;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.widget.TextViewCompat;
import java.util.Random;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class CharPortraitView extends AppCompatTextView {
private boolean isRandom = false;
private Random random;
private int mBackColor;
private Context mContext;
private String[] colors;
private boolean mHead=true;
private String mContent;
public CharPortraitView(Context context) {
this(context, null);
}
public CharPortraitView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init(attrs);
build();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = View.MeasureSpec.getSize(heightMeasureSpec);
int minSize = Math.min(width, height);
setMeasuredDimension(minSize, minSize);
}
private void init(AttributeSet attrs) {
// 初始化随机数
random = new Random();
// 获取参数
TypedArray array = mContext.obtainStyledAttributes(attrs, R.styleable.CharPortraitView);
// 获取是否随机背景
isRandom = array.getBoolean(R.styleable.CharPortraitView_random, false);
// 获取背景颜色
mBackColor = array.getColor(R.styleable.CharPortraitView_back_color, Color.BLUE);
array.recycle();
}
//设置
private void build() {
if (!isRandom) {
mBackColor = getRandomColor(); //产生随机颜色
}
// 设置居中
setGravity(Gravity.CENTER);
// 设置自适应文字大小
TextViewCompat.setAutoSizeTextTypeWithDefaults(this, TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
// 设置背景颜色
setBackgroundResource(R.drawable.shape_drawable);
GradientDrawable drawable = (GradientDrawable) getBackground();
drawable.setColor(mBackColor);
setBackgroundDrawable(drawable);
if (mContent==null){
return;
}
if (mHead){
setText(mContent.substring(0, 1));//取首字符显示
}else {
setText(mContent.substring(mContent.length()-1, mContent.length()));//取末尾字符显示
}
}
/**
* 设置文本内容
*@param mHead true 第一个字符 false 最后一个字符
*@return
*/
public CharPortraitView setHead(boolean mHead) {
this.mHead=mHead;
build();
return this;
}
//设置文本内容
public CharPortraitView setContent(String str) {
this.mContent=str;
build();
return this;
}
//设置背景颜色
public CharPortraitView setBackColor(int backColor) {
mBackColor = backColor;
isRandom = false;
build();
return this;
}
//设置是否开启随机颜色
public CharPortraitView setRandom(boolean isRandom) {
this.isRandom = isRandom;
build();
return this;
}
/**
* 设置随机背景颜色数组
* @param colors
* @return
*/
public CharPortraitView setBackColor(String[] colors){
this.colors=colors;
build();
return this;
}
/**
* 获取随机背景颜色
* @return
*/
private int getRandomColor() {
String[] colorArray;
if (colors!=null&&colors.length>0){
colorArray=colors;
}else {
colorArray=mContext.getResources().getStringArray(R.array.color);
}
int value = random.nextInt(colorArray.length);
return Color.parseColor(colorArray[value]);
}
}
该类主要是实现清除搜索栏的内容
package com.example.lastmodel;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.animation.Animation;
import android.view.animation.CycleInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.EditText;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class ClearEditText extends androidx.appcompat.widget.AppCompatEditText implements OnFocusChangeListener, TextWatcher {
private Drawable mClearDrawable;
public ClearEditText(Context context) {
this(context, null);
}
public ClearEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.editTextStyle);
}
public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
mClearDrawable = getResources().getDrawable(R.drawable.guanbifanhuishanchu);
}
mClearDrawable.setBounds(-17, 5, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
setClearIconVisible(false);
setOnFocusChangeListener(this);
addTextChangedListener(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (getCompoundDrawables()[2] != null) {
if (event.getAction() == MotionEvent.ACTION_UP) {
boolean touchable = event.getX() > (getWidth()
- getPaddingRight() - mClearDrawable.getIntrinsicWidth())
&& (event.getX() < ((getWidth() - getPaddingRight())));
if (touchable) {
this.setText("");
}
}
}
return super.onTouchEvent(event);
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
setClearIconVisible(getText().length() > 0);
} else {
setClearIconVisible(false);
}
}
protected void setClearIconVisible(boolean visible) {
Drawable right = visible ? mClearDrawable : null;
setCompoundDrawables(getCompoundDrawables()[0],
getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
}
@Override
public void onTextChanged(CharSequence s, int start, int count,
int after) {
setClearIconVisible(s.length() > 0);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
public void setShakeAnimation(){
this.setAnimation(shakeAnimation(5));
}
public static Animation shakeAnimation(int counts){
Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
translateAnimation.setInterpolator(new CycleInterpolator(counts));
translateAnimation.setDuration(1000);
return translateAnimation;
}
}
数据库的创建
package com.example.lastmodel;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
import androidx.annotation.Nullable;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String Create_Table_User = "create table Use (" + "name text," + "telnumber text)";
private Context mContext;
public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(Create_Table_User);
//Toast.makeText(mContext,"创建成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
package com.example.lastmodel;
import java.util.Comparator;
public class PinyinComparator implements Comparator<SortModel> {
public int compare(SortModel o1, SortModel o2) {
if (o1.getLetters().equals("@")
|| o2.getLetters().equals("#")) {
return -1;
} else if (o1.getLetters().equals("#")
|| o2.getLetters().equals("@")) {
return 1;
} else {
return o1.getLetters().compareTo(o2.getLetters());
}
}
}
package com.example.lastmodel;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class PinyinUtils {
/**
* 获取拼音
*
* @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 (char curChar : input) {
if (Character.toString(curChar).matches("[\\u4E00-\\u9FA5]+")) {
/*至少匹配一个汉字的写法,这两个unicode值正好时Unicode表中的汉字的头和尾
* []代表里面的值出现一个就可以, 后边的"+"代表至少出现1次,合起来即至少匹配一个汉字*/
String[] temp = PinyinHelper.toHanyuPinyinStringArray(curChar, format);
output += temp[0];
} else
output += Character.toString(curChar);
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
return output;
}
/**
* 获取第一个字的拼音首字母
* @param chinese
* @return
*/
public static String getFirstSpell(String chinese) {
StringBuffer pinYinBF = new StringBuffer();
char[] arr = chinese.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (char curChar : arr) {
if (curChar > 128) {
try {
String[] temp = PinyinHelper.toHanyuPinyinStringArray(curChar, defaultFormat);
if (temp != null) {
pinYinBF.append(temp[0].charAt(0));
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
} else {
pinYinBF.append(curChar);
}
}
return pinYinBF.toString().replaceAll("\\W", "").trim();
}
}
右边侧滑栏的实现
package com.example.lastmodel;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class SideBar extends View {
// 触摸事件
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
public static String[] b = {
"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 int choose = -1;
private Paint paint = new Paint();
private TextView mTextDialog;
/**
* 为SideBar设置显示字母的TextView
* @param textDialog
*/
public void setTextView(TextView textDialog) {
this.mTextDialog = textDialog;
}
public SideBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SideBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SideBar(Context context) {
super(context);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
int singleHeight = height / b.length;
for (int i = 0; i < b.length; i++) {
paint.setColor(Color.rgb(105, 105, 105));
// paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
paint.setTextSize(35);
if (i == choose) {
paint.setColor(Color.parseColor("#3399ff"));
paint.setFakeBoldText(true);
}
float xPos = width / 2 - paint.measureText(b[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(b[i], xPos, yPos, paint);
paint.reset();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * b.length);
switch (action) {
case MotionEvent.ACTION_UP:
setBackground(new ColorDrawable(0x00000000));
choose = -1;
invalidate();
if (mTextDialog != null) {
mTextDialog.setVisibility(View.INVISIBLE);
}
break;
default:
setBackgroundResource(R.drawable.sidebar_background);
if (oldChoose != c) {
if (c >= 0 && c < b.length) {
if (listener != null) {
listener.onTouchingLetterChanged(b[c]);
}
if (mTextDialog != null) {
mTextDialog.setText(b[c]);
mTextDialog.setVisibility(View.VISIBLE);
}
choose = c;
invalidate();
}
}
break;
}
return true;
}
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
public interface OnTouchingLetterChangedListener {
void onTouchingLetterChanged(String s);
}
}
首字母排序功能
package com.example.lastmodel;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
/**
* @author: hanxuan
* @date: 2020/12/2
*/
public class SortAdapter extends RecyclerView.Adapter<SortAdapter.ViewHolder> {
private LayoutInflater mInflater;
private List<SortModel> mData;
private Context mContext;
public SortAdapter(Context context, List<SortModel> data) {
mInflater = LayoutInflater.from(context);
mData = data;
this.mContext = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.item, parent,false);
ViewHolder viewHolder = new ViewHolder(view);
viewHolder.tvTag = view.findViewById(R.id.tag);
viewHolder.tvName = view.findViewById(R.id.name);
return viewHolder;
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
int section = getSectionForPosition(position);
//如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
if (position == getPositionForSection(section)) {
holder.tvTag.setVisibility(View.VISIBLE);
holder.tvTag.setText(mData.get(position).getLetters());
holder.portrait.setContent(mData.get(position).getName()).setHead(true);
} else {
holder.tvTag.setVisibility(View.GONE);
holder.portrait.setContent(mData.get(position).getName()).setHead(true);
}
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(holder.itemView, position);
}
});
}
holder.tvName.setText(this.mData.get(position).getName());
holder.tvName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, mData.get(position).getName(),Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return mData.size();
}
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
private OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
this.mOnItemClickListener = mOnItemClickListener;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvTag, tvName;
private CharPortraitView portrait;
public ViewHolder(View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.name);
portrait = itemView.findViewById(R.id.user_img);
}
}
/**
* 提供给Activity刷新数据
* @param list
*/
public void updateList(List<SortModel> list){
this.mData = list;
notifyDataSetChanged();
}
public Object getItem(int position) {
return mData.get(position);
}
/**
* 根据ListView的当前位置获取分类的首字母的char ascii值
*/
public int getSectionForPosition(int position) {
return mData.get(position).getLetters().charAt(0);
}
/**
* 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置
*/
public int getPositionForSection(int section) {
for (int i = 0; i < getItemCount(); i++) {
String sortStr = mData.get(i).getLetters();
char firstChar = sortStr.toUpperCase().charAt(0);
if (firstChar == section) {
return i;
}
}
return -1;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tag"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#ffffff"
android:gravity="center_vertical"
android:paddingLeft="15dp"
android:text="A"
android:textColor="#000000" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<com.example.lastmodel.CharPortraitView
android:id="@+id/user_img"
android:layout_width="40dp"
android:layout_height="40dp"
android:textColor="#ffffff"
android:layout_centerVertical="true"
android:padding="5dp"/>
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginLeft="20dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/user_img"
android:gravity="center_vertical"
android:textSize="20sp"
android:textColor="#000000"
/>
<View
android:id="@+id/view_lv_item_line"
android:layout_width="320dp"
android:layout_height="0.05dp"
android:layout_below="@+id/name"
android:layout_alignParentLeft="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="30dp"
android:layout_marginRight="30dp"
android:background="#C0C0C0"
android:paddingBottom="15dp" />
RelativeLayout>
LinearLayout>
实体类
package com.example.lastmodel;
public class SortModel {
private String telnumber;
private String name;
private String letters;//显示拼音的首字母
public SortModel(String name) {
this.name = name;
}
public SortModel(String telnumber, String name) {
this.telnumber = telnumber;
this.name = name;
}
public SortModel() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLetters() {
return letters;
}
public void setLetters(String letters) {
this.letters = letters;
}
@Override
public String toString() {
return "SortModel{" +
"name='" + name + '\'' +
", letters='" + letters + '\'' +
'}';
}
}
接下来就是资源类的文件了
shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp"/>
<stroke android:width="1dp"
android:color="#bcb8b8"/>
<size android:width="320dp"
/>
<solid android:color="#F5F5F5" />
shape>
shape_drawable.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/holo_red_light"/>
shape>
sidebar_background.xml
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffff"/>
<corners
android:topLeftRadius="8dp"
android:bottomLeftRadius="8dp"/>
shape>
arrys.xml
<resources>
<string-array name="color">
<item>#FFBBFFitem>
<item>#A8A8A8item>
<item>#EEC591item>
<item>#D8BFD8item>
<item>#CAE1FFitem>
<item>#BC8F8Fitem>
<item>#CDB79Eitem>
<item>#EEE8AAitem>
<item>#C5C1AAitem>
<item>#C1CDC1item>
string-array>
resources>
attrs.xml
<resources>
<declare-styleable name="CharPortraitView">
<attr name="back_color" format="reference"/>
<attr name="random" format="boolean"/>
declare-styleable>
resources>
OK,以上就是全部的代码了,有些图片资源我没有附上去,那不太重要,可以自己找几张。仅供大家参考,若有侵权,请联系本人立即删除。