Android-自定義View之 可換行的radioGroup 和 字母索引

public class CheckBoxGroup extends LinearLayout {

    private HashSet<Integer> checkedList = new HashSet<>();
    private CompoundButton.OnCheckedChangeListener mOnCheckedChangeListener;
    private int marginLeft=10,marginTop=10;//初始化子view的間距
    public CheckBoxGroup(Context context) {
        super(context);
        setOrientation(VERTICAL);
    }

    public CheckBoxGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CheckBoxGroup);
        marginLeft = a.getDimensionPixelSize(R.styleable.CheckBoxGroup_childMarginLeft,10);
        marginTop = a.getDimensionPixelSize(R.styleable.CheckBoxGroup_childMarginTop,10);
        a.recycle();
        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int maxWidth = MeasureSpec.getSize(widthMeasureSpec);//獲取最大寬度
        int x=0,y=0,row=0;//初始化group的左邊距和上邊距和行數,x和y也用來記錄測量子view累加的寬高
        int maxHeight=0;
        for(int index = 0;index<getChildCount();index++){//循環遍歷子view
            final View child = getChildAt(index);
            if(child.getVisibility()!=View.GONE){
                //UNSPECIFIED表示不限定子view大小,EXACTLY實際值,父容器指定具體的值,AT_MOST父容器提供最大值
                child.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);//測量子view寬高
                int width = child.getMeasuredWidth(),height = child.getMeasuredHeight();
                if(height>maxHeight)//獲取這一行中最高的子view
                    maxHeight=height;
                x+=width+marginLeft;//將測量到的寬度添加到x中
                if(row<1){
                    y=maxHeight+marginTop;//將測量到的高度添加進來
                }
                //當累加的寬度大於最大寬度時
                if(x>maxWidth){
                    if(index != 0){//防止第一個view就大於最大寬度
                        row++;
                    }
                    if(width>=maxWidth-marginLeft){//如果這個view比最大寬度還要寬,那x直接設爲最大寬度
                        x = maxWidth;
                    }else{
                        x=width+marginLeft;//否則就充值當前x
                    }
                    y+=maxHeight+marginTop;//增加行數後高度也得累加
                    maxHeight = 0;//重置最大高度,開始下一行的計算

                }
            }
        }
        setMeasuredDimension(maxWidth,y);//設置容器需要的寬度和高度
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int maxWidth=r-1;//獲取最大寬度
        int x = 0,y = 0,row = 0;
        int maxHeight = 0;
        for(int index = 0;index < getChildCount();index++){
            View child=getChildAt(index);
            if(child.getVisibility()!=GONE){
                int width = child.getMeasuredWidth(),height = child.getMeasuredHeight();
                if(height>maxHeight)
                    maxHeight = height;
                x+=width+marginLeft;
                if(row<1){
                    y=maxHeight+marginTop;
                }
                if(x>maxWidth){
                    if(index!=0)
                        row++;
                    if(width>=maxWidth-marginLeft){
                        x=maxWidth;
                    }else {
                        x=width+marginLeft;
                    }
                    y+=maxHeight+marginTop;
                    maxHeight=0;
                }
                child.layout(x-width,y-height,x,y);
            }
        }


    }

    private void init() {
        mOnCheckedChangeListener=new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if(b){
                    checkedList.add(compoundButton.getId());
                }else {
                    checkedList.remove(compoundButton.getId());
                }
            }
        };
    }


    @Override
    public void addView(View child) {
        if(child instanceof CheckBox){
            CheckBox checkBox = (CheckBox) child;
            if(checkBox.isChecked()){
                setCheckIdList(checkBox.getId());
            }
            checkBox.setOnCheckedChangeListener(mOnCheckedChangeListener);
        }
        super.addView(child);
    }

    private void setCheckIdList(@IdRes int id) {
        checkedList.add(id);
    }

    public void clearChecked(){
        checkedList.clear();
    }
    private void removeChecked(@IdRes int id){
        checkedList.remove(id);
    }


}

 

attr.xml文件:

<resources>
    <declare-styleable name="CheckBoxGroup">
        <attr name="childMarginLeft" format="dimension"/>
        <attr name="childMarginTop" format="dimension"/>
    </declare-styleable>
</resources>
public class ScreenCheckBox extends CheckBox {

    public ScreenCheckBox(Context context) {
        super(context);
        setTextStyle();
        setOnCheckChangeLiistener();
    }
    private void setOnCheckChangeLiistener(){
        this.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b) {
                    compoundButton.setText("√" + compoundButton.getText());
                    compoundButton.setTextColor(Color.parseColor("#d52c34"));
                }else if (compoundButton.getText().toString().contains("√")){
                    compoundButton.setText(getText().subSequence(1, compoundButton.getText().length()));
                    compoundButton.setTextColor(Color.parseColor("#000000"));
                }
            }
        });
    }
    private void setTextStyle(){
        setBackgroundResource(R.drawable.bg_checkbox);
        setButtonTintMode(PorterDuff.Mode.CLEAR);
        if (isChecked()) {
            setText("√" + getText());
            setTextColor(Color.parseColor("#d52c34"));
        }
    }
    public String getCheckBoxText(){
        if (getText().toString().contains("√")){
            return getText().toString().substring(1);
        }else
            return getText().toString();
    }

}

drawable文件下新建3個xml文件bg_checkbox,bg_check_red,bg_check_gray:

bg_checkbox:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/bg_check_red" android:state_checked="true"/>
    <item android:drawable="@drawable/bg_check_gray" android:state_checked="false"/>
</selector>
bg_check_red:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="3dp" />
    <stroke
        android:width="1dp"
        android:color="#d52c3d" />
</shape>

 

接下來是字母索引:

自定義View  繼承View,重寫onDraw方法

 

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(33, 65, 98));
            // paint.setColor(Color.WHITE);
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);
            paint.setTextSize(30);
            // 選中的狀態
            if (i == choose) {
//                paint.setColor(Color.parseColor("#3399ff"));
                paint.setColor(getResources().getColor(R.color.maincolor));
                paint.setFakeBoldText(true);
            }
            // x座標等於中間-字符串寬度的一半.
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            float yPos = singleHeight * i + singleHeight;
            canvas.drawText(b[i], xPos, yPos, paint);
            paint.reset();// 重置畫筆
        }

    }
 public boolean dispatchTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        final float y = event.getY();// 點擊y座標
        final int oldChoose = choose;
        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
        final int c = (int) (y / getHeight() * b.length);// 點擊y座標所佔總高度的比例*b數組的長度就等於點擊b中的個數.

        switch (action) {
            case MotionEvent.ACTION_UP:
                setBackgroundDrawable(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;
    }
/**
 * 向外公開的方法
 *
 * @param onTouchingLetterChangedListener
 */
public void setOnTouchingLetterChangedListener(
        OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
    this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}

/**
 * 接口
 *
 * @author coder
 *
 */
public interface OnTouchingLetterChangedListener {
    public void onTouchingLetterChanged(String s);
}

在activity頁面:

//設置右側觸摸監聽
sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {

    @Override
    public void onTouchingLetterChanged(String s) {
        //該字母首次出現的位置
        if (isall) {
            int position = adapter.getPositionForSection(s.charAt(0));
            if (position != -1) {
                selectCarBrand.setSelection(position);//selectCarBrand是個listview
            }
        }
    }
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章