android ScrollView中嵌套字母索引自定位view,半屏时可以使用Scrollview 滑动展示不全的索引字母

半屏时索引列表展示不全问题,通过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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FW_G8Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值