很多应用中我们都能看到SlideBar的使用,如:微信,QQ,美团等等,最常见的应该就是通讯录里面对联系人进行A~Z、#的排序。侧边栏主要是方便用户进行字母索引。
我们就不BB了,直接上代码
xml属性:
<declare-styleable name="SlideBar">
<!--Select the effect-->
<attr name="specialEffect">
<enum name="none" value="0" />
<enum name="rectangle" value="1" />
</attr>
<!--DataSource-->
<attr name="data" format="string" />
<!--standard source-->
<attr name="standard" format="string" />
<!--The background color of the selected time-->
<attr name="chooseColor" format="color" />
<!--Unselected background color-->
<attr name="unChooseColor" format="color" />
<!--The font color of the selected time-->
<attr name="chooseTextColor" format="color" />
<!--The color of the unselected font-->
<attr name="unChooseTextColor" format="color" />
</declare-styleable>
SliBar源码:
public class SlideBar extends View {
private static final String TAG = "SlideBar";
public SlideBar(Context context) {
super(context);
init(context, null);
}
public SlideBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public SlideBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SlideBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
//DataSource
private String[] data;
//standard source
private String standard;
//Calculate the height of a single character based on the number of data sources
private int singleHeight;
//brush
private Paint paint;
//Current selected location
private int choose;
//Open an additional selected condition
private boolean additionalConditions;
//Select the effect
private SpecialEffect specialEffect;
//The background color of the selected time
private int chooseColor;
//Unselected background color
private int unChooseColor;
//The font color of the selected time
private int chooseTextColor;
//The color of the unselected font
private int unChooseTextColor;
/**
* initialize
*/
private void init(Context context, AttributeSet attrs) {
paint = new Paint();
choose = -1;
additionalConditions = true;
if (null != attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideBar);
/********************************************************************/
String slideBarData = a.getString(R.styleable.SlideBar_data);
if (TextUtils.isEmpty(slideBarData)) {
data = 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", "#"};
} else {
data = slideBarData.split(",");
}
/********************************************************************/
standard = a.getString(R.styleable.SlideBar_standard);
if (TextUtils.isEmpty(standard)) {
getStandard();
} else {
standard = standard.substring(0, 1);
}
/********************************************************************/
int slideBarChooseColor = a.getColor(R.styleable.SlideBar_chooseColor, -1);
if (slideBarChooseColor == -1) {
chooseColor = getResources().getColor(R.color.color_dc);
} else {
chooseColor = slideBarChooseColor;
}
/********************************************************************/
int slideBarUnChooseColor = a.getColor(R.styleable.SlideBar_unChooseColor, -1);
if (slideBarUnChooseColor == -1) {
unChooseColor = getResources().getColor(android.R.color.transparent);
} else {
unChooseColor = slideBarUnChooseColor;
}
/********************************************************************/
int slideBarChooseTextColor = a.getColor(R.styleable.SlideBar_chooseTextColor, -1);
if (slideBarChooseTextColor == -1) {
chooseTextColor = getResources().getColor(android.R.color.holo_red_dark);
} else {
chooseTextColor = slideBarChooseTextColor;
}
/********************************************************************/
int slideBarUnChooseTextColor = a.getColor(R.styleable.SlideBar_unChooseTextColor, -1);
if (slideBarUnChooseTextColor == -1) {
unChooseTextColor = getResources().getColor(android.R.color.black);
} else {
unChooseTextColor = slideBarUnChooseTextColor;
}
/********************************************************************/
switch (a.getInteger(R.styleable.SlideBar_specialEffect, 0)) {
case 0:
specialEffect = SpecialEffect.NONE;
break;
case 1:
specialEffect = SpecialEffect.RECTABGLE;
break;
}
} else {
data = 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", "#"};
getStandard();
chooseColor = getResources().getColor(R.color.color_dc);
unChooseColor = getResources().getColor(android.R.color.transparent);
chooseTextColor = getResources().getColor(android.R.color.holo_red_dark);
unChooseTextColor = getResources().getColor(android.R.color.black);
specialEffect = SpecialEffect.NONE;
}
if (specialEffect == SpecialEffect.NONE) {
setBackgroundColor(unChooseColor);
}
}
/**
* When the standard source is not set, the method of manually obtaining the standard source is obtained
*/
private void getStandard() {
paint.setTextSize(20);
int count = data == null ? 0 : data.length;
float[] dataWidth = new float[count];
String[] newData = new String[count];
for (int i = 0; i < count; i++) {
newData[i] = data[i];
dataWidth[i] = paint.measureText(data[i]);
}
paint.reset();
for (int i = 0; i < count; i++) {
for (int j = i + 1; j < count; j++) {
if (dataWidth[i] < dataWidth[j]) {
//Sort the width of the string
float stamp = dataWidth[i];
dataWidth[i] = dataWidth[j];
dataWidth[j] = stamp;
//Sort string
String variable = newData[i];
newData[i] = newData[j];
newData[j] = variable;
}
}
}
if (count % 2 == 0) {
standard = newData[count / 2];
} else {
standard = newData[(count + 1) / 2];
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Calculate the available width
int usableWidth = getWidth() - getPaddingLeft() - getPaddingRight(),
usableHeight = getHeight() - getPaddingTop() - getPaddingBottom();
//Get the number of data sources
int count = data == null ? 0 : data.length;
//Calculate the height of a single character based on the number of data sources
singleHeight = usableHeight / count;
//Draw the character of the loop data source
for (int i = 0; i < count; i++) {
if (i == choose && additionalConditions) {
if (specialEffect == SpecialEffect.RECTABGLE) {
paint.setColor(chooseColor);
paint.setAntiAlias(true);
if (usableWidth > singleHeight) {
int median = usableWidth - singleHeight;
canvas.drawRect(new RectF(getPaddingLeft() + median / 2f, getPaddingTop() + singleHeight * i,
getPaddingLeft() + usableWidth - median / 2f, getPaddingTop() + singleHeight * (i + 1)), paint);
} else {
int median = singleHeight - usableWidth;
canvas.drawRect(new RectF(getPaddingLeft(), getPaddingTop() + singleHeight * i + median / 2f,
getPaddingLeft() + usableWidth, getPaddingTop() + singleHeight * (i + 1) - median / 2f), paint);
}
paint.reset();
}
paint.setColor(chooseTextColor);
} else {
paint.setColor(unChooseTextColor);
}
paint.setFakeBoldText(false);
paint.setAntiAlias(true);//anti-aliasing
float textSize = usableWidth / 2f >= singleHeight ? singleHeight : usableWidth / 2f;
paint.setTextSize(textSize);
/***********************************************************/
float offx = usableWidth / 2 - paint.measureText(data[i]) / 2 + getPaddingLeft(),
offy = singleHeight * (i + 0.5f) + getPaddingTop() + paint.measureText(standard) / 2;
canvas.drawText(data[i], offx, offy, paint);
paint.reset();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent e) {
float y = e.getY();
int currentChoose = (int) ((y - getPaddingTop()) / singleHeight);
int count = data == null ? 0 : data.length;
switch (e.getAction()) {
case MotionEvent.ACTION_UP:
if (specialEffect == SpecialEffect.NONE) {
setBackgroundColor(unChooseColor);
}
if (null != mTextDialog) {
if (mTextDialog.isShown()) {
mTextDialog.setVisibility(GONE);
}
}
choose = -1;
invalidate();
break;
default:
if (specialEffect == SpecialEffect.NONE) {
setBackgroundColor(chooseColor);
}
if (choose != currentChoose) {
if (currentChoose >= 0 && currentChoose < count) {
if (null != slideListening) {
slideListening.slideChange(data[currentChoose]);
}
if (null != mTextDialog) {
mTextDialog.setText(data[currentChoose]);
if (!mTextDialog.isShown()) {
mTextDialog.setVisibility(VISIBLE);
}
}
choose = currentChoose;
invalidate();
}
}
break;
}
super.dispatchTouchEvent(e);
return true;
}
/**
* Set the selected position
*
* @param choose
*/
public void setChoose(int choose) {
this.choose = choose;
invalidate();
}
/**
* Set additional selection criteria
*
* @param additionalConditions
*/
public void setAdditionalConditions(boolean additionalConditions) {
this.additionalConditions = additionalConditions;
invalidate();
}
/**
* Set the sliding effect
*
* @param specialEffect
*/
public void setSpecialEffect(SpecialEffect specialEffect) {
this.specialEffect = specialEffect;
if (specialEffect == SpecialEffect.NONE) {
setBackgroundColor(unChooseColor);
} else {
setBackgroundColor(getResources().getColor(android.R.color.transparent));
}
invalidate();
}
/**
* Set up the data source
*
* @param data
*/
public void setData(String[] data) {
this.data = data;
getStandard();
invalidate();
}
/**
* Set up the data standard source
*
* @param standard
*/
public void setStandard(String standard) {
this.standard = standard;
invalidate();
}
/**
* Set the background color
*
* @param chooseColor Color type
*/
public void setChooseColor(int chooseColor) throws ColorExceptions {
if (chooseColor == -1) {
throw new ColorExceptions();
}
this.chooseColor = chooseColor;
invalidate();
}
/**
* Sets the unselected background color
*
* @param unChooseColor Color type
*/
public void setUnChooseColor(int unChooseColor) throws ColorExceptions {
if (unChooseColor == -1) {
throw new ColorExceptions();
}
this.unChooseColor = unChooseColor;
if (specialEffect == SpecialEffect.NONE) {
setBackgroundColor(unChooseColor);
} else {
setBackgroundColor(getResources().getColor(android.R.color.transparent));
}
invalidate();
}
/**
* @param chooseColor Check the background color, Color type
* @param unChooseColor Unselected background color, Color type
*/
public void setBackgroundColor(int chooseColor, int unChooseColor) throws ColorExceptions {
if (chooseColor == -1 || unChooseColor == -1) {
throw new ColorExceptions();
}
this.chooseColor = chooseColor;
this.unChooseColor = unChooseColor;
invalidate();
}
/**
* Sets the color of the selected font
*
* @param chooseTextColor Color type
*/
public void setChooseTextColor(int chooseTextColor) throws ColorExceptions {
if (chooseTextColor == -1) {
throw new ColorExceptions();
}
this.chooseTextColor = chooseTextColor;
invalidate();
}
/**
* Sets the color of the unselected font
*
* @param unChooseTextColor Color type
*/
public void setUnChooseTextColor(int unChooseTextColor) throws ColorExceptions {
if (unChooseTextColor == -1) {
throw new ColorExceptions();
}
this.unChooseTextColor = unChooseTextColor;
invalidate();
}
/**
* @param chooseTextColor Check font color, Color type
* @param unChooseTextColor Unselected font color, Color type
*/
public void setTextColor(int chooseTextColor, int unChooseTextColor) throws ColorExceptions {
if (chooseTextColor == -1 || unChooseTextColor == -1) {
throw new ColorExceptions();
}
this.chooseTextColor = chooseTextColor;
this.unChooseTextColor = unChooseTextColor;
invalidate();
}
private TextView mTextDialog;
/**
* This is a simple open text view that displays the letters
*
* @param mTextDialog
*/
public void setTextDialog(TextView mTextDialog) {
this.mTextDialog = mTextDialog;
if (mTextDialog.isShown()) {
mTextDialog.setVisibility(GONE);
}
}
private SlideListening slideListening;
/**
* Add slide listening
*
* @param slideListening
*/
public void addSlideListening(SlideListening slideListening) {
this.slideListening = slideListening;
}
/**
* Swipes the inner class
*/
public interface SlideListening {
void slideChange(String c);
}
/**
* Enumerations that are displayed when selected
*/
public enum SpecialEffect {
NONE,
RECTABGLE
}
@Override
public String toString() {
return "SlideBar{" +
"data=" + Arrays.toString(data) +
", standard='" + standard + '\'' +
", specialEffect=" + specialEffect +
", chooseColor=" + chooseColor +
", unChooseColor=" + unChooseColor +
", chooseTextColor=" + chooseTextColor +
", unChooseTextColor=" + unChooseTextColor +
'}';
}
}
调用:
<com.taoyong.widget.SlideBar
android:id="@+id/slideBar"
android:layout_width="82dp"
android:layout_height="match_parent"
android:paddingBottom="60dp"
android:paddingLeft="60dp"
android:paddingTop="60dp"
app:chooseColor="#64ff0000"
app:chooseTextColor="#9500ff"
app:data="Q,W,E,R,D,F,J,K,L,U,I,O,1,2,3,4,5,6"
app:specialEffect="none"
app:standard="D"
app:unChooseColor="#c7b9b9"
app:unChooseTextColor="#00ff08" />
SlideBar slideBar = (SlideBar) findViewById(R.id.slideBar);
textView = (TextView) findViewById(R.id.textView);
slideBar.setTextDialog(textView);
slideBar.setSpecialEffect(SlideBar.SpecialEffect.RECTABGLE);
//slideBar.setChooseColor(getResources().getColor(android.R.color.holo_green_light));
//slideBar.setChoose(1);
slideBar.addSlideListening(new SlideBar.SlideListening() {
@Override
public void slideChange(String c) {
Log.d(TAG, "slideChange: " + c);
}
});
https://github.com/fountaintao/CustomControl/tree/master/widget/src/main/java/com/taoyong/widget
建议:下载后-直接运行demo,看一下效果,有需要的也可以在demo上更改,自己所需要的样式!
有问题?希望反馈,在BUG中成长!