自定义viewAndroid知识Android开发

通讯录A-Z指示器Demo

2017-04-29  本文已影响107人  大批

:)

**from** bing 17/**04**/2**9**

本文主要是介绍了一个自定义控件的实现

**Demo**就是这个样儿 **^_^**

选择实现方案,是继承View还是ViewGroup

这个demo就选择继承View吧


总体思路


下面有大量代码

                                [↓][↓][↓]
                                [↓][↓][↓]
                                [↓][↓][↓]
                          [↓][↓][↓][↓][↓][↓][↓]
                                [↓][↓][↓]
                                   [↓]

定义控件会用到的属性

/**
     *
     * 最大的字体
     *
     */
    private int maxTextSize = DEFAULT_MAX_TEXT_SIZE;

    /**
     *
     * 最小的字体
     *
     */
    private int minTextSize = DEFAULT_MIN_TEXT_SIZE;

    /**
     *
     * 不同字体之间的间隔
     *
     */
    private int textSizeStep = DEFAULT_TEXT_STEP;

    /**
     *
     * 选中的时候字体颜色
     *
     */
    private int choiseTextColor = DEFAULT_CHOISE_COLOR;

    /**
     *
     * 默认的字体颜色
     *
     */
    private int defaultTextColor = DEFAULT_COLOR;


    /**
     *
     * 字符上下间距
     *
     *
     */
    private int margin = 8;

    private static final int DEFAULT_MAX_TEXT_SIZE = 100;//px
    private static final int DEFAULT_MIN_TEXT_SIZE = 15;
    private static final int DEFAULT_TEXT_STEP = 10;
    private static final int DEFAULT_CHOISE_COLOR = Color.BLACK;
    private static final int DEFAULT_COLOR = Color.GRAY;

    /**
     *
     * 默认的选中位置
     *
     *
     */
    private int currentChoise = 0;

建立一个实体类来保存每个字符的位置信息(在滑动和绘制的时候判断位置)

class TextSizeModel {

        private int x;
        private int y;
        private int textSize;

        private String item;
    }

控件高度的确定(这个肯定就是重写 onMeasure了)


 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int width = maxTextSize + margin * 2;
        int height = margin * 2;

        if(datas == null || datas.size() == 0){
            setMeasuredDimension(width,height);
            return;
        }

        currentChoise = datas.size() / 2;
        //height += initItemTextSize();

        for(int i = 0;i < datas.size();i++){
            int duration = i < currentChoise ? currentChoise - i : i - currentChoise;
            int textSize = maxTextSize - duration * textSizeStep;
            textSize = textSize < minTextSize ? minTextSize : textSize;
            datas.get(i).setTextSize(textSize);

            height += textSize + margin;
        }

        setMeasuredDimension(width,height);

    }


有了字体大小,接下来就是绘制了(onDraw)

@Override
    protected void onDraw(Canvas canvas) {

        int currentY = margin + maxTextSize;
        for(int i = 0;i < datas.size();i++){
            paint.setColor(i == currentChoise ? choiseTextColor : defaultTextColor);
            paint.setTextSize(datas.get(i).getTextSize());
            canvas.drawText(datas.get(i).getItem(),
                    getMeasuredWidth() / 2,currentY,paint);
            datas.get(i).setX(0);
            datas.get(i).setY(currentY);
            currentY += datas.get(i).getTextSize() + margin;
        }

    }


滑动的监听(onTouchEvent)


@Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                for(int i=0;i < datas.size();i++){
                    TextSizeModel model = datas.get(i);
                    if(model.getY() < y && model.getY() + margin > y){
                        currentChoise = i;
                        break;
                    }
                }
                initItemTextSize();
                postInvalidate();
                break;
            case MotionEvent.ACTION_UP:
                break;
        }

        return true;
    }


源码

package com.suse.yuxin.emptydemo.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.suse.yuxin.emptydemo.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/4/29.
 */

public class LettersView extends View{

    /**
     *
     * 最大的字体
     *
     */
    private int maxTextSize = DEFAULT_MAX_TEXT_SIZE;

    /**
     *
     * 最小的字体
     *
     */
    private int minTextSize = DEFAULT_MIN_TEXT_SIZE;

    /**
     *
     * 不同字体之间的间隔
     *
     */
    private int textSizeStep = DEFAULT_TEXT_STEP;

    /**
     *
     * 选中的时候字体颜色
     *
     */
    private int choiseTextColor = DEFAULT_CHOISE_COLOR;

    /**
     *
     * 默认的字体颜色
     *
     */
    private int defaultTextColor = DEFAULT_COLOR;


    /**
     *
     * 字符上下间距
     *
     *
     */
    private int margin = 8;

    private static final int DEFAULT_MAX_TEXT_SIZE = 100;//px
    private static final int DEFAULT_MIN_TEXT_SIZE = 15;
    private static final int DEFAULT_TEXT_STEP = 10;
    private static final int DEFAULT_CHOISE_COLOR = Color.BLACK;
    private static final int DEFAULT_COLOR = Color.GRAY;

    /**
     *
     * 默认的选中位置
     *
     *
     */
    private int currentChoise = 0;

    private Paint paint;
    private List<TextSizeModel> datas = new ArrayList<>();


    private static final String LOG_TAG = "LettersView_TAG";

    public LettersView(Context context) {
        super(context);
        init(context,null);
    }

    public LettersView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }

    public LettersView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }


    private void init(Context context,AttributeSet attrs) {
        if(attrs == null){
            return;
        }
        //init attr
        TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.LettersView);
        maxTextSize = (int) arr.getDimension(R.styleable.LettersView_maxTextSize,DEFAULT_MAX_TEXT_SIZE);
        minTextSize = (int) arr.getDimension(R.styleable.LettersView_minTextSize,DEFAULT_MIN_TEXT_SIZE);
        textSizeStep = (int) arr.getDimension(R.styleable.LettersView_textStep,DEFAULT_TEXT_STEP);
        choiseTextColor = arr.getColor(R.styleable.LettersView_choiseTextColor,DEFAULT_CHOISE_COLOR);
        defaultTextColor = arr.getColor(R.styleable.LettersView_defaultTextColor,DEFAULT_COLOR);
        arr.recycle();

        Log.i(LOG_TAG,"maxT "+maxTextSize+"  minT"+minTextSize+"   step "+textSizeStep);

        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setTextAlign(Paint.Align.CENTER);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int width = maxTextSize + margin * 2;
        int height = margin * 2;

        if(datas == null || datas.size() == 0){
            setMeasuredDimension(width,height);
            return;
        }

        currentChoise = datas.size() / 2;
        //height += initItemTextSize();

        for(int i = 0;i < datas.size();i++){
            int duration = i < currentChoise ? currentChoise - i : i - currentChoise;
            int textSize = maxTextSize - duration * textSizeStep;
            textSize = textSize < minTextSize ? minTextSize : textSize;
            datas.get(i).setTextSize(textSize);

            height += textSize + margin;
        }

        setMeasuredDimension(width,height);

    }


    private int initItemTextSize(){
        int height = 0;
        for(int i = 0;i < datas.size();i++){
            int duration = i < currentChoise ? currentChoise - i : i - currentChoise;
            int textSize = maxTextSize - duration * textSizeStep;
            textSize = textSize < minTextSize ? minTextSize : textSize;
            datas.get(i).setTextSize(textSize);

            height += textSize + margin;
        }
        return height;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        int currentY = margin + maxTextSize;
        for(int i = 0;i < datas.size();i++){
            paint.setColor(i == currentChoise ? choiseTextColor : defaultTextColor);
            paint.setTextSize(datas.get(i).getTextSize());
            canvas.drawText(datas.get(i).getItem(),
                    getMeasuredWidth() / 2,currentY,paint);
            datas.get(i).setX(0);
            datas.get(i).setY(currentY);
            currentY += datas.get(i).getTextSize() + margin;
        }

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                for(int i=0;i < datas.size();i++){
                    TextSizeModel model = datas.get(i);
                    if(model.getY() < y && model.getY() + margin > y){
                        currentChoise = i;
                        break;
                    }
                }
                initItemTextSize();
                postInvalidate();
                break;
            case MotionEvent.ACTION_UP:
                break;
        }

        return true;
    }



    public void setData(List<String> letters){
        if(letters == null || letters.size() == 0){
            return;
        }
        datas.clear();
        for (String letter : letters) {
            TextSizeModel sizeModel = new TextSizeModel();
            sizeModel.setItem(letter);
            datas.add(sizeModel);
        }
        requestLayout();
    }


    public void setData(String[] letters){
        if(letters == null || letters.length == 0){
            return;
        }
        List<String> l = new ArrayList<>();
        for(int i=0;i < letters.length;i++){
            l.add(letters[i]);
        }
        setData(l);
    }


    class TextSizeModel {

        private int x;
        private int y;
        private int textSize;

        private String item;

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        public int getTextSize() {
            return textSize;
        }

        public void setTextSize(int textSize) {
            this.textSize = textSize;
        }

        public String getItem() {
            return item;
        }

        public void setItem(String item) {
            this.item = item;
        }
    }

}

<declare-styleable name="LettersView">
        <attr name="maxTextSize" format="dimension"/>
        <attr name="minTextSize" format="dimension"/>
        <attr name="choiseTextColor" format="color"/>
        <attr name="defaultTextColor" format="color"/>
        <attr name="textStep" format="color"></attr>
    </declare-styleable>


如何使用


public class LettersTestActivity  extends AppCompatActivity{


    LettersView lettersView;


    String[] letters = 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"
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_letters_test);
        lettersView = (LettersView) findViewById(R.id.activity_letters_test_content);
        lettersView.setData(letters);
    }
}

Nothing is certain in this life. The only thing i know for sure is that. I love you and my life. That is the only thing i know. have a good day

上一篇下一篇

猜你喜欢

热点阅读