半屏时索引列表展示不全问题,通过ScrollView包裹即可实现使用
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:background="@android:color/background_dark"
android:gravity="center">
<Button
android:id="@+id/bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="切换半屏"
/>
<com.test.testapp.MyScrollView
android:id="@+id/scroll"
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_marginTop="100dp"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.test.testapp.IndexTitleScrollView
android:id="@+id/lsb"
android:layout_width="100dp"
android:layout_height="662dp"
android:layout_alignParentLeft="true" />
</RelativeLayout>
</com.test.testapp.MyScrollView>
<TextView
android:id="@+id/tv_center_char"
android:layout_width="190dp"
android:layout_height="190dp"
android:layout_centerInParent="true"
android:background="@color/colorAccent"
android:textColor="@color/colorPrimaryDark"
android:gravity="center"
android:textSize="70sp"
android:visibility="visible" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity implements MyScrollView.IOnScrollXY,IndexTitleScrollView.OnIndexListener {
private String TAG = "MainActivity";
public static boolean isFull = true;
private MyScrollView mScrollview;
private IndexTitleScrollView mlsb;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mScrollview = findViewById(R.id.scroll);
mScrollview.setOnScrollXYLinstener(this);
mlsb = findViewById(R.id.lsb);
textView = findViewById(R.id.tv_center_char);
mlsb.registIndexChanged(this);
findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.i(TAG, "click");
if (isFull) {
//切换半屏
...
isFull =false;
} else {
//切换全屏
...
isFull =true;
}
}
});
}
@Override
public void onTouchScrollXY(float downx, float downY) {
if(mlsb !=null){
mlsb.setChar(downY);
}
}
@Override
public void onIndexChanged(int index, char c) {
textView.setText("" + c);
textView.setVisibility(View.VISIBLE);
}
@Override
public void onStopChanged(int index, char c) {
textView.setVisibility(View.VISIBLE);
}
@Override
public void onClickChar(int index, char c) {
textView.setText("" + c);
}
@Override
protected void onDestroy() {
super.onDestroy();
mlsb.registIndexChanged(null);
}
}
MyScrollView.java
public class MyScrollView extends ScrollView {
private String TAG ="MyScrollView";
public IOnScrollXY iOnScrollXY;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i(TAG,"isFull ="+MainActivity.isFull);
if(MainActivity.isFull){
return super.onInterceptTouchEvent(ev);
}else {
return false;
}
}
private float downX;
private float downY;
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(!MainActivity.isFull){
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = ev.getRawX();
downY = getScrollY()+ev.getRawY();
if(iOnScrollXY !=null){
iOnScrollXY.onTouchScrollXY(downX,downY);
}
Log.i(TAG, "onTouchEvent downX = " + downX +" downY = "+downY);
}
}
return super.onTouchEvent(ev);
}
public void setOnScrollXYLinstener(IOnScrollXY xy){
this.iOnScrollXY = xy;
}
public interface IOnScrollXY{
void onTouchScrollXY(float downx, float downY);
}
}
IndexTitleScrollView.java
/**
* 自定义的首字母滑动条,半屏时通过ScrollView滑动显示
*
* @author
*/
public class IndexTitleScrollView extends View {
public static final String TAG = "IndexTitleScrollView";
private int height;
private int width;
private final char[] chars = {'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', '#'};// 5+13+9
private int mIndex = 0;
private OnIndexListener mChanged;
Paint paint;
private final int textSize = 14;
private float iHeight;
private boolean isScroll = false;
private boolean isEnabl = true;
public IndexTitleScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
Log.i(TAG, "IndexTitleScrollView ");
paint = new Paint();
paint.setTextAlign(Paint.Align.CENTER); // 文字对齐,CENTER表示绘制的文字居中显示
paint.setTextSize(textSize);
paint.setStrokeWidth(0.7f); //设置描边宽度
paint.setAntiAlias(true);//抗锯齿 - [避免绘制的视图边缘有模糊毛边,呈锯齿形]
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(Color.BLACK);
}
/**
* 光标位置,(0~26)
*
* @param index
*/
public void setIndex(int index) {
if (index >= 0 && index <= 26) {
this.mIndex = index;
invalidate();
}
}
/**
* 得到当前的位置
*
* @return
*/
public int getCurrentIndex() {
return mIndex;
}
/**
* 得到当前的字符
*
* @return
*/
public char getCurrentChar() {
return chars[mIndex];
}
/**
* 光标所指的字符,(A ~Z,#)
*
* @param c
*/
public void setIndex(char c) {
setIndex(findCharIndex(c));
}
private int findCharIndex(char c) {
Log.i(TAG,"findCharIndex = "+c);
for (int i = 0; i < chars.length; i++) {
if (chars[i] == c) {
return i;
}
}
return -1;
}
public void registIndexChanged(OnIndexListener mIndexChanged) {
mChanged = mIndexChanged;
}
public void refresh(){
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (height == 0)
height = 662;//;
// height = getHeight();
if (width == 0)
width = getWidth();
Log.i(TAG, "width->" + getWidth() +"::>height="+height);
// Log.i(TAG, "height->" + getHeight());
if (iHeight == 0) {
iHeight = ((float) height / (float) (chars.length));
int[] location = new int[2];
getLocationOnScreen(location);
view_x = location[0];
view_y = location[1];
view_x = width / 2;
Log.i(TAG, "view_x->" + view_x);
Log.i(TAG, "view_y->" + view_y);
}
// Log.i(TAG, "iHeight->" + iHeight);
for (int i = 0; i < chars.length; i++) {
paint.setColor(Color.TRANSPARENT);
//canvas.drawRect(0, (float) i * iHeight, getRight(), iHeight * (float) (i + 1), paint);
paint.setTextSize(textSize * 0.93f);
if (i == mIndex) {
paint.setColor(Color.RED);
} else {
paint.setColor(Color.WHITE);
}
// cos30 = 0.866 cos60 = 0.5
if(MainActivity.isFull){
if (isCicle) {
if (i == mIndex - 2) {
canvas.drawText(chars[i] + "", view_x + 20, (float) i * iHeight+12, paint);
} else if (i == mIndex - 1) {
canvas.drawText(chars[i] + "", view_x + 30, (float) i * iHeight+12, paint);
} else if (i == mIndex) {
canvas.drawText(chars[i] + "", view_x + 40, (float) i * iHeight+12, paint);
} else if (i == mIndex + 1) {
canvas.drawText(chars[i] + "", view_x + 30, (float) i * iHeight+12, paint);
} else if (i == mIndex + 2) {
canvas.drawText(chars[i] + "", view_x + 20, (float) i * iHeight+12, paint);
} else {
canvas.drawText(chars[i] + "", view_x, (float) i * iHeight+12, paint);
}
} else {
canvas.drawText(chars[i] + "", view_x, (float) i * iHeight+12, paint);
}
}else {
canvas.drawText(chars[i] + "", view_x, (float) i * iHeight+12, paint);
}
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i(TAG,"dispatchTouchEvent ="+MainActivity.isFull);
if(MainActivity.isFull){
return super.dispatchTouchEvent(event);
}else {
return false;
}
}
private float downX;
private float downY;
private boolean isCicle = false;
@Override
public boolean onTouchEvent(MotionEvent event) {
// 记录按下的坐标
if (event.getAction() == MotionEvent.ACTION_DOWN) {
downX = event.getRawX();
downY = event.getRawY();
Log.i(TAG, "onTouchEvent downX = " + downX +" downY = "+downY);
}
if (event.getAction() == MotionEvent.ACTION_UP) {
// x,y移动的距离小于10就出发点击事件
if (Math.abs(downX - event.getRawX()) < 10 && Math.abs(downY - event.getRawY()) < 10) {
int index = (int) ((event.getRawY() - view_y) / iHeight);
Log.i(TAG, "onclick here index =" + index);
setIndex(index);
onClickChar(index);
} else {
isCicle = false;
invalidate();
onStopChanged(mIndex);
}
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
isCicle = true;
float x = event.getRawX();
float y = event.getRawY();
// Log.i(TAG, "; move x ->" + x + "; move y ->" +
// y);
if (x > getRight()) {
Log.i(TAG, "IS OVER ");
// do nothing
} else {
refreshIndex(x, y);
}
}
return isEnabl;
}
private int view_x;
private int view_y;
// 刷新位置值,同时刷新视图
private void refreshIndex(float x, float y) {
// TODO Auto-generated method stub
Log.i(TAG, "refreshIndex ");
if (view_y + mIndex * iHeight < y
&& y < (mIndex + 1) * iHeight + view_y) {
// index不需要改变,
// do nothing
// Log.i(TAG, "no need change");
} else {
float i = (y - view_y) / iHeight;
// Log.i(TAG, "index will is " + i);
if (i < 0 || (int) i > chars.length - 1) {
} else {
mIndex = (int) i;
Log.i(TAG, "refreshIndex mIndex = "+mIndex);
invalidate();
onIndexChanged(mIndex);
}
}
}
public void setChar(float Y){
Log.d(TAG,"set char is full ="+MainActivity.isFull);
if(!MainActivity.isFull){
int index = (int) ((Y - view_y) / iHeight);
Log.i(TAG, "onclick here index =" + index);
setIndex(index);
onClickChar(index);
invalidate();
}
}
/**
* 监听首字母定位事件
*/
public interface OnIndexListener {
public void onIndexChanged(int index, char c);
public void onStopChanged(int index, char c);
public void onClickChar(int index, char c);
}
private void onIndexChanged(int index) {
isScroll = true;
if (mChanged != null)
mChanged.onIndexChanged(index, chars[index]);
}
private void onStopChanged(int index) {
isScroll = false;
if (mChanged != null)
mChanged.onStopChanged(index, chars[index]);
}
private void onClickChar(int index) {
isScroll = false;
if (mChanged != null)
mChanged.onClickChar(index, chars[index]);
}
public boolean isScroll() {
return isScroll;
}
public void isEnabled(boolean isenabl ){
isEnabl = isenabl;
}
}