实训第七周(1)

本周开始写WheelView——滚轮控件

我想要实现的设置生日日期,地区的方式都是用户可在可选时间,地区列表中滚动选择

所以需用到滚轮,先写滚轮控件

(1)初始化,获取设置的属性

attr.xml

<declare-styleable name="WheelView">
        <attr name="unitHeight" format="dimension" />
        <attr name="itemNumber" format="integer"/>

        <attr name="normalTextColor" format="color" />
        <attr name="normalTextSize" format="dimension" />
        <attr name="selectedTextColor" format="color" />
        <attr name="selectedTextSize" format="dimension" />

        <attr name="lineColor" format="color" />
        <attr name="lineHeight" format="dimension" />

        <attr name="maskHeight" format="dimension"/>
        <attr name="noEmpty" format="boolean"/>
        <attr name="isEnable" format="boolean"/>
    </declare-styleable>

    private void init(Context context, AttributeSet attrs) {

        TypedArray attribute = context.obtainStyledAttributes(attrs, R.styleable.WheelView);
        unitHeight = (int) attribute.getDimension(R.styleable.WheelView_unitHeight, unitHeight);//单元格高度
        itemNumber = attribute.getInt(R.styleable.WheelView_itemNumber, itemNumber);//显示多少个内容

        normalFont = attribute.getDimension(R.styleable.WheelView_normalTextSize, normalFont);//默认字体
        selectedFont = attribute.getDimension(R.styleable.WheelView_selectedTextSize, selectedFont);//选中时字体
        normalColor = attribute.getColor(R.styleable.WheelView_normalTextColor, normalColor);//默认字体颜色
        selectedColor = attribute.getColor(R.styleable.WheelView_selectedTextColor, selectedColor);//选中时候的字体颜色

        lineColor = attribute.getColor(R.styleable.WheelView_lineColor, lineColor);//线的默认颜色
        lineHeight = attribute.getDimension(R.styleable.WheelView_lineHeight, lineHeight);//线的默认宽度

        maskHeight = attribute.getDimension(R.styleable.WheelView_maskHeight, maskHeight);//蒙版高度
        noEmpty = attribute.getBoolean(R.styleable.WheelView_noEmpty, true);//是否允许选
        isEnable = attribute.getBoolean(R.styleable.WheelView_isEnable, true);//是否可用

        attribute.recycle();

        controlHeight = itemNumber * unitHeight;
    }

(2)初始化数据

    private void initData() {
        isClearing = true;
        itemList.clear();
        for (int i = 0; i < dataList.size(); i++) {
            ItemObject itemObject = new ItemObject();
            itemObject.id = i;
            itemObject.itemText = dataList.get(i);
            itemObject.x = 0;
            itemObject.y = i * unitHeight;
            itemList.add(itemObject);
        }
        isClearing = false;
    }

其中,ItemObject(单条内容)

    private class ItemObject {
        /**id*/
        public int id = 0;
        /*** 内容*/
        public String itemText = "";
        /*** x坐标*/
        public int x = 0;
        /*** y坐标*/
        public int y = 0;
        /*** 移动距离*/
        public int move = 0;
        /*** 字体画笔*/
        private TextPaint textPaint;
        /*** 字体范围矩形*/
        private Rect textRect;

        public ItemObject() {
            super();
        }

        /**
         * 绘制自身
         *
         * @param canvas         画板
         * @param containerWidth 容器宽度
         */
        public void drawSelf(Canvas canvas, int containerWidth) {

            if (textPaint == null) {
                textPaint = new TextPaint();
                textPaint.setAntiAlias(true);//防止锯齿
            }

            if (textRect == null)
                textRect = new Rect();

            // 判断是否被选择
            if (isSelected()) {
                textPaint.setColor(selectedColor);
                // 获取距离标准位置的距离
                float moveToSelect = moveToSelected();
                moveToSelect = moveToSelect > 0 ? moveToSelect : moveToSelect * (-1);
                // 计算当前字体大小
                float textSize = normalFont
                        + ((selectedFont - normalFont) * (1.0f - moveToSelect / (float) unitHeight));
                textPaint.setTextSize(textSize);
            } else {
                textPaint.setColor(normalColor);
                textPaint.setTextSize(normalFont);
            }

            // 返回包围整个字符串的最小的一个Rect区域
            itemText = (String) TextUtils.ellipsize(itemText, textPaint, containerWidth, TextUtils.TruncateAt.END);
            textPaint.getTextBounds(itemText, 0, itemText.length(), textRect);
            // 判断是否可视
            if (!isInView())
                return;

            // 绘制内容
            canvas.drawText(itemText, x + controlWidth / 2 - textRect.width() / 2,
                    y + move + unitHeight / 2 + textRect.height() / 2, textPaint);

        }

        /*** 是否在可视界面内*/
        public boolean isInView() {
            if (y + move > controlHeight || (y + move + unitHeight / 2 + textRect.height() / 2) < 0)
                return false;
            return true;
        }

        /*** 移动距离*/
        public void move(int _move) {
            this.move = _move;
        }

        /*** 设置新的坐标*/
        public void newY(int _move) {
            this.move = 0;
            this.y = y + _move;
        }

        /*** 判断是否在选择区域内*/
        public boolean isSelected() {
            if ((y + move) >= controlHeight / 2 - unitHeight / 2 + lineHeight
                    && (y + move) <= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                return true;
            }
            if ((y + move + unitHeight) >= controlHeight / 2 - unitHeight / 2 + lineHeight
                    && (y + move + unitHeight) <= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                return true;
            }
            if ((y + move) <= controlHeight / 2 - unitHeight / 2 + lineHeight
                    && (y + move + unitHeight) >= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                return true;
            }
            return false;
        }

        /*** 获取移动到标准位置需要的距离*/
        public float moveToSelected() {
            return (controlHeight / 2 - unitHeight / 2) - (y + move);
        }
    }

(3)绘制线条

    private void drawLine(Canvas canvas) {

        if (linePaint == null) {
            linePaint = new Paint();
            linePaint.setColor(lineColor);
            linePaint.setAntiAlias(true);
            linePaint.setStrokeWidth(lineHeight);//设置画笔宽度
        }

        canvas.drawLine(0, controlHeight / 2 - unitHeight / 2 + lineHeight,
                controlWidth, controlHeight / 2 - unitHeight / 2 + lineHeight, linePaint);
        canvas.drawLine(0, controlHeight / 2 + unitHeight / 2 - lineHeight,
                controlWidth, controlHeight / 2 + unitHeight / 2 - lineHeight, linePaint);
    }

(4)绘制列表

    private synchronized void drawList(Canvas canvas) {
        if (isClearing)
            return;
        try {
            for (ItemObject itemObject : itemList) {
                itemObject.drawSelf(canvas, getMeasuredWidth());
            }
        } catch (Exception e) {
        }
    }

(5) 触摸事件

获取纵坐标(设置时间,滚轮是纵向移动)

获得的触摸动作为:

a. ACTION_DOWN(按下)

    设置为正在滑动中, 获取当下纵坐标,以及当时系统时间

b. ACTION_MOVE(移动中)

    刷新移动的距离,设置滑动监听

c. ACTION_UP(抬起时)

    计算出这段时间移动的距离

    若滑动时间小于预先设定的短促移动时间并且滑动距离大于预先设定的短促移动距离,则继续移动一段距离

    否则,移动到指定位置,停止移动(actionUp)

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnable)
            return true;
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isScrolling = true;
                downY = (int) event.getY();
                downTime = System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:
                actionMove(y - downY);
                onSelectListener();
                break;
            case MotionEvent.ACTION_UP:
                int move = Math.abs(y - downY);
                // 判断这段时间移动的距离
                if (System.currentTimeMillis() - downTime < goonTime && move > goonDistance) {
                    goonMove(y - downY);
                } else {
                    actionUp(y - downY);
                    noEmpty();
                    isScrolling = false;
                }
                break;
            default:
                break;
        }
        return true;
    }

(6)继续移动一段距离

    private synchronized void goonMove(final int move) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                int distance = 0;
                while (distance < unitHeight * MOVE_NUMBER) {
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    actionThreadMove(move > 0 ? distance : distance * (-1));
                    distance += 10;

                }
                actionUp(move > 0 ? distance - 10 : distance * (-1) + 10);
                noEmpty();
            }
        }).start();
    }

(7)不能为空,必须有选择

    private void noEmpty() {
        if (!noEmpty)
            return;
        for (ItemObject item : itemList) {
            if (item.isSelected())
                return;
        }
        int move = (int) itemList.get(0).moveToSelected();
        if (move < 0) {
            defaultMove(move);
        } else {
            defaultMove((int) itemList.get(itemList.size() - 1)
                    .moveToSelected());
        }
        for (ItemObject item : itemList) {
            if (item.isSelected()) {
                if (onSelectListener != null)
                    onSelectListener.endSelect(item.id, item.itemText);
                break;
            }
        }
    }

(8)移动的时候,即触摸事件中,触摸动作为ACTION_MOVE时所作处理

移动触摸时滑动的距离,刷新控件

    private void actionMove(int move) {
        for (ItemObject item : itemList) {
            item.move(move);
        }
        invalidate();
    }

(9)移动,线程中调用

向handler发送刷新信息,移动

    private void actionThreadMove(int move) {
        for (ItemObject item : itemList) {
            item.move(move);
        }
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);
    }

(10)松开的时候

当向上滑动和向下滑动时,分别获取所需移动的距离,监听器结束选择

缓慢移动之前所获得的所需移动距离

通知刷新

    private void actionUp(int move) {
        int newMove = 0;
        if (move > 0) {
            for (int i = 0; i < itemList.size(); i++) {
                if (itemList.get(i).isSelected()) {
                    newMove = (int) itemList.get(i).moveToSelected();
                    if (onSelectListener != null)
                        onSelectListener.endSelect(itemList.get(i).id,
                                itemList.get(i).itemText);
                    break;
                }
            }
        } else {
            for (int i = itemList.size() - 1; i >= 0; i--) {
                if (itemList.get(i).isSelected()) {
                    newMove = (int) itemList.get(i).moveToSelected();
                    if (onSelectListener != null)
                        onSelectListener.endSelect(itemList.get(i).id,
                                itemList.get(i).itemText);
                    break;
                }
            }
        }
        for (ItemObject item : itemList) {
            item.newY(move + 0);
        }
        slowMove(newMove);
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);

    }

(11)缓慢移动

先判断是向上滑动还是向下滑动的(移动距离取绝对值),设置移动的速度(1)

当还需继续移动时,每移动一格,重设每一项纵坐标,通知刷新,线程睡眠2ms, 移动距离减一,直到已移动完所需距离

每一项结束监听

    private synchronized void slowMove(final int move) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                // 判断正负
                int m = move > 0 ? move : move * (-1);
                int i = move > 0 ? 1 : (-1);
                // 移动速度
                int speed = 1;
                while (true) {
                    m = m - speed;
                    if (m <= 0) {
                        for (ItemObject item : itemList) {
                            item.newY(m * i);
                        }
                        Message rMessage = new Message();
                        rMessage.what = REFRESH_VIEW;
                        handler.sendMessage(rMessage);
                        try {
                            Thread.sleep(2);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        break;
                    }
                    for (ItemObject item : itemList) {
                        item.newY(speed * i);
                    }
                    Message rMessage = new Message();
                    rMessage.what = REFRESH_VIEW;
                    handler.sendMessage(rMessage);
                    try {
                        Thread.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (ItemObject item : itemList) {
                    if (item.isSelected()) {
                        if (onSelectListener != null)
                            onSelectListener.endSelect(item.id, item.itemText);
                        break;
                    }
                }

            }
        }).start();
    }

(12)滑动监听

    private void onSelectListener() {
        if (onSelectListener == null)
            return;
        for (ItemObject item : itemList) {
            if (item.isSelected()) {
                onSelectListener.selecting(item.id, item.itemText);
            }
        }
    }

(13)选择监听

    public interface OnSelectListener {
        /*** 结束选择*/
        void endSelect(int id, String text);
        /*** 选中的内容*/
        void selecting(int id, String text);

    }
}



附上完整WheelView.java

package com.ezreal.ezchat.timeselectview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.ezreal.ezchat.R;

import java.util.ArrayList;

/**
 * Created by 张静
 */

/*** WheelView滚轮*/
public class WheelView extends View {
    /*** 控件宽度*/
    private float controlWidth;
    /*** 控件高度*/
    private float controlHeight;
    /*** 是否滑动中*/
    private boolean isScrolling = false;
    /*** 选择的内容*/
    private ArrayList<ItemObject> itemList = new ArrayList<>();
    /*** 设置数据*/
    private ArrayList<String> dataList = new ArrayList<>();
    /*** 按下的坐标*/
    private int downY;
    /*** 按下的时间*/
    private long downTime = 0;
    /*** 短促移动*/
    private long goonTime = 200;
    /*** 短促移动距离*/
    private int goonDistance = 100;
    /*** 画线画笔*/
    private Paint linePaint;
    /*** 线的默认颜色*/
    private int lineColor = 0xff000000;
    /*** 线的默认宽度*/
    private float lineHeight = 2f;
    /*** 默认字体*/
    private float normalFont = 14.0f;
    /*** 选中的时候字体*/
    private float selectedFont = 22.0f;
    /*** 单元格高度*/
    private int unitHeight = 50;
    /*** 显示多少个内容*/
    private int itemNumber = 7;
    /*** 默认字体颜色*/
    private int normalColor = 0xff000000;
    /*** 选中时候的字体颜色*/
    private int selectedColor = 0xffff0000;
    /*** 蒙板高度*/
    private float maskHeight = 48.0f;
    /*** 选择监听*/
    private OnSelectListener onSelectListener;
    /*** 是否可用*/
    private boolean isEnable = true;
    /*** 刷新界面*/
    private static final int REFRESH_VIEW = 0x001;
    /*** 移动距离*/
    private static final int MOVE_NUMBER = 5;
    /*** 是否允许选*/
    private boolean noEmpty = true;
    /**正在修改数据,避免ConcurrentModificationException异常*/
    private boolean isClearing = false;

    public WheelView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
        initData();
    }

    public WheelView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
        initData();
    }

    public WheelView(Context context) {
        super(context);
        initData();
    }

    /*** 初始化,获取设置的属性*/
    private void init(Context context, AttributeSet attrs) {

        TypedArray attribute = context.obtainStyledAttributes(attrs, R.styleable.WheelView);
        unitHeight = (int) attribute.getDimension(R.styleable.WheelView_unitHeight, unitHeight);
        itemNumber = attribute.getInt(R.styleable.WheelView_itemNumber, itemNumber);

        normalFont = attribute.getDimension(R.styleable.WheelView_normalTextSize, normalFont);
        selectedFont = attribute.getDimension(R.styleable.WheelView_selectedTextSize, selectedFont);
        normalColor = attribute.getColor(R.styleable.WheelView_normalTextColor, normalColor);
        selectedColor = attribute.getColor(R.styleable.WheelView_selectedTextColor, selectedColor);

        lineColor = attribute.getColor(R.styleable.WheelView_lineColor, lineColor);
        lineHeight = attribute.getDimension(R.styleable.WheelView_lineHeight, lineHeight);

        maskHeight = attribute.getDimension(R.styleable.WheelView_maskHeight, maskHeight);
        noEmpty = attribute.getBoolean(R.styleable.WheelView_noEmpty, true);
        isEnable = attribute.getBoolean(R.styleable.WheelView_isEnable, true);

        attribute.recycle();

        controlHeight = itemNumber * unitHeight;
    }

    /*** 初始化数据*/
    private void initData() {
        isClearing = true;
        itemList.clear();
        for (int i = 0; i < dataList.size(); i++) {
            ItemObject itemObject = new ItemObject();
            itemObject.id = i;
            itemObject.itemText = dataList.get(i);
            itemObject.x = 0;
            itemObject.y = i * unitHeight;
            itemList.add(itemObject);
        }
        isClearing = false;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        controlWidth = getMeasuredWidth();
        if (controlWidth != 0) {
            setMeasuredDimension(getMeasuredWidth(), itemNumber * unitHeight);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawLine(canvas);
        drawList(canvas);
        drawMask(canvas);
    }

    /*** 绘制线条*/
    private void drawLine(Canvas canvas) {

        if (linePaint == null) {
            linePaint = new Paint();
            linePaint.setColor(lineColor);
            linePaint.setAntiAlias(true);
            linePaint.setStrokeWidth(lineHeight);
        }

        canvas.drawLine(0, controlHeight / 2 - unitHeight / 2 + lineHeight,
                controlWidth, controlHeight / 2 - unitHeight / 2 + lineHeight, linePaint);
        canvas.drawLine(0, controlHeight / 2 + unitHeight / 2 - lineHeight,
                controlWidth, controlHeight / 2 + unitHeight / 2 - lineHeight, linePaint);
    }

    private synchronized void drawList(Canvas canvas) {
        if (isClearing)
            return;
        try {
            for (ItemObject itemObject : itemList) {
                itemObject.drawSelf(canvas, getMeasuredWidth());
            }
        } catch (Exception e) {
        }
    }

    /*** 绘制遮盖板*/
    private void drawMask(Canvas canvas) {
        LinearGradient lg = new LinearGradient(0, 0, 0, maskHeight, 0x00f2f2f2,
                0x00f2f2f2, TileMode.MIRROR);
        Paint paint = new Paint();
        paint.setShader(lg);
        canvas.drawRect(0, 0, controlWidth, maskHeight, paint);

        LinearGradient lg2 = new LinearGradient(0, controlHeight - maskHeight,
                0, controlHeight, 0x00f2f2f2, 0x00f2f2f2, TileMode.MIRROR);
        Paint paint2 = new Paint();
        paint2.setShader(lg2);
        canvas.drawRect(0, controlHeight - maskHeight, controlWidth,
                controlHeight, paint2);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnable)
            return true;
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isScrolling = true;
                downY = (int) event.getY();
                downTime = System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:
                actionMove(y - downY);
                onSelectListener();
                break;
            case MotionEvent.ACTION_UP:
                int move = Math.abs(y - downY);
                // 判断这段时间移动的距离
                if (System.currentTimeMillis() - downTime < goonTime && move > goonDistance) {
                    goonMove(y - downY);
                } else {
                    actionUp(y - downY);
                    noEmpty();
                    isScrolling = false;
                }
                break;
            default:
                break;
        }
        return true;
    }

    /*** 继续移动一定距离*/
    private synchronized void goonMove(final int move) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                int distance = 0;
                while (distance < unitHeight * MOVE_NUMBER) {
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    actionThreadMove(move > 0 ? distance : distance * (-1));
                    distance += 10;

                }
                actionUp(move > 0 ? distance - 10 : distance * (-1) + 10);
                noEmpty();
            }
        }).start();
    }

    /*** 不能为空,必须有选项*/
    private void noEmpty() {
        if (!noEmpty)
            return;
        for (ItemObject item : itemList) {
            if (item.isSelected())
                return;
        }
        int move = (int) itemList.get(0).moveToSelected();
        if (move < 0) {
            defaultMove(move);
        } else {
            defaultMove((int) itemList.get(itemList.size() - 1)
                    .moveToSelected());
        }
        for (ItemObject item : itemList) {
            if (item.isSelected()) {
                if (onSelectListener != null)
                    onSelectListener.endSelect(item.id, item.itemText);
                break;
            }
        }
    }

    /*** 移动的时候*/
    private void actionMove(int move) {
        for (ItemObject item : itemList) {
            item.move(move);
        }
        invalidate();
    }

    /*** 移动,线程中调用*/
    private void actionThreadMove(int move) {
        for (ItemObject item : itemList) {
            item.move(move);
        }
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);
    }

    /*** 松开的时候*/
    private void actionUp(int move) {
        int newMove = 0;
        if (move > 0) {
            for (int i = 0; i < itemList.size(); i++) {
                if (itemList.get(i).isSelected()) {
                    newMove = (int) itemList.get(i).moveToSelected();
                    if (onSelectListener != null)
                        onSelectListener.endSelect(itemList.get(i).id,
                                itemList.get(i).itemText);
                    break;
                }
            }
        } else {
            for (int i = itemList.size() - 1; i >= 0; i--) {
                if (itemList.get(i).isSelected()) {
                    newMove = (int) itemList.get(i).moveToSelected();
                    if (onSelectListener != null)
                        onSelectListener.endSelect(itemList.get(i).id,
                                itemList.get(i).itemText);
                    break;
                }
            }
        }
        for (ItemObject item : itemList) {
            item.newY(move + 0);
        }
        slowMove(newMove);
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);

    }

    /*** 缓慢移动*/
    private synchronized void slowMove(final int move) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                // 判断正负
                int m = move > 0 ? move : move * (-1);
                int i = move > 0 ? 1 : (-1);
                // 移动速度
                int speed = 1;
                while (true) {
                    m = m - speed;
                    if (m <= 0) {
                        for (ItemObject item : itemList) {
                            item.newY(m * i);
                        }
                        Message rMessage = new Message();
                        rMessage.what = REFRESH_VIEW;
                        handler.sendMessage(rMessage);
                        try {
                            Thread.sleep(2);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        break;
                    }
                    for (ItemObject item : itemList) {
                        item.newY(speed * i);
                    }
                    Message rMessage = new Message();
                    rMessage.what = REFRESH_VIEW;
                    handler.sendMessage(rMessage);
                    try {
                        Thread.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (ItemObject item : itemList) {
                    if (item.isSelected()) {
                        if (onSelectListener != null)
                            onSelectListener.endSelect(item.id, item.itemText);
                        break;
                    }
                }

            }
        }).start();
    }

    /**
     * 移动到默认位置
     *
     * @param move
     */
    private void defaultMove(int move) {
        for (ItemObject item : itemList) {
            item.newY(move);
        }
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);
    }
    /*** 滑动监听*/
    private void onSelectListener() {
        if (onSelectListener == null)
            return;
        for (ItemObject item : itemList) {
            if (item.isSelected()) {
                onSelectListener.selecting(item.id, item.itemText);
            }
        }
    }
    /*** 设置数据 (第一次)*/
    public void setData(ArrayList<String> data) {
        this.dataList = data;
        initData();
    }
    /*** 获取返回项 id*/
    public int getSelected() {
        for (ItemObject item : itemList) {
            if (item.isSelected())
                return item.id;
        }
        return -1;
    }
    /*** 获取返回的内容*/
    public String getSelectedText() {
        for (ItemObject item : itemList) {
            if (item.isSelected())
                return item.itemText;
        }
        return "";
    }
    /*** 是否可用*/
    public boolean isEnable() {
        return isEnable;
    }
    /*** 设置是否可用*/
    public void setEnable(boolean isEnable) {
        this.isEnable = isEnable;
    }
    /*** 设置默认选项*/
    public void setDefault(int index) {
        if (index > itemList.size() - 1)
            return;
        float move = itemList.get(index).moveToSelected();
        defaultMove((int) move);
    }
    /*** 获取列表大小*/
    public int getListSize() {
        if (itemList == null)
            return 0;
        return itemList.size();
    }
    /** 监听*/
    public void setOnSelectListener(OnSelectListener onSelectListener) {
        this.onSelectListener = onSelectListener;
    }

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case REFRESH_VIEW:
                    invalidate();
                    break;
                default:
                    break;
            }
        }

    };

    /*** 单条内容*/
    private class ItemObject {
        /**id*/
        public int id = 0;
        /*** 内容*/
        public String itemText = "";
        /*** x坐标*/
        public int x = 0;
        /*** y坐标*/
        public int y = 0;
        /*** 移动距离*/
        public int move = 0;
        /*** 字体画笔*/
        private TextPaint textPaint;
        /*** 字体范围矩形*/
        private Rect textRect;

        public ItemObject() {
            super();
        }

        /**
         * 绘制自身
         *
         * @param canvas         画板
         * @param containerWidth 容器宽度
         */
        public void drawSelf(Canvas canvas, int containerWidth) {

            if (textPaint == null) {
                textPaint = new TextPaint();
                textPaint.setAntiAlias(true);
            }

            if (textRect == null)
                textRect = new Rect();

            // 判断是否被选择
            if (isSelected()) {
                textPaint.setColor(selectedColor);
                // 获取距离标准位置的距离
                float moveToSelect = moveToSelected();
                moveToSelect = moveToSelect > 0 ? moveToSelect : moveToSelect * (-1);
                // 计算当前字体大小
                float textSize = normalFont
                        + ((selectedFont - normalFont) * (1.0f - moveToSelect / (float) unitHeight));
                textPaint.setTextSize(textSize);
            } else {
                textPaint.setColor(normalColor);
                textPaint.setTextSize(normalFont);
            }

            // 返回包围整个字符串的最小的一个Rect区域
            itemText = (String) TextUtils.ellipsize(itemText, textPaint, containerWidth, TextUtils.TruncateAt.END);
            textPaint.getTextBounds(itemText, 0, itemText.length(), textRect);
            // 判断是否可视
            if (!isInView())
                return;

            // 绘制内容
            canvas.drawText(itemText, x + controlWidth / 2 - textRect.width() / 2,
                    y + move + unitHeight / 2 + textRect.height() / 2, textPaint);

        }

        /*** 是否在可视界面内*/
        public boolean isInView() {
            if (y + move > controlHeight || (y + move + unitHeight / 2 + textRect.height() / 2) < 0)
                return false;
            return true;
        }

        /*** 移动距离*/
        public void move(int _move) {
            this.move = _move;
        }

        /*** 设置新的坐标*/
        public void newY(int _move) {
            this.move = 0;
            this.y = y + _move;
        }

        /*** 判断是否在选择区域内*/
        public boolean isSelected() {
            if ((y + move) >= controlHeight / 2 - unitHeight / 2 + lineHeight
                    && (y + move) <= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                return true;
            }
            if ((y + move + unitHeight) >= controlHeight / 2 - unitHeight / 2 + lineHeight
                    && (y + move + unitHeight) <= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                return true;
            }
            if ((y + move) <= controlHeight / 2 - unitHeight / 2 + lineHeight
                    && (y + move + unitHeight) >= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                return true;
            }
            return false;
        }

        /*** 获取移动到标准位置需要的距离*/
        public float moveToSelected() {
            return (controlHeight / 2 - unitHeight / 2) - (y + move);
        }
    }

    /*** 选择监听*/
    public interface OnSelectListener {
        /*** 结束选择*/
        void endSelect(int id, String text);
        /*** 选中的内容*/
        void selecting(int id, String text);

    }
}

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值