【Android】App首页上下滚动快报控件 通知控件 类似京东快报控件(一)

前言

快过年了,对于大伙来说手头上的事情做完没有呢,马上也该让自己轻松一阵子了,哈哈哈。好,说正事,由于公司App这个版本首页的改版,新增了很多新的控件,类似于京东快报这种控件的话我在写之前也去找了一下轮子,但是遗憾的是并没有发现简单易用的哈,所以就琢磨自己来实现。

实现思路

快报功能其实也就文字上下滚动,然后给用户一个简单的文字提示,我并不想做太复杂, 而且咱家的产品大大也不需要很复杂的快报功能,所以我就想做个极简的吧。
大致控件需要包括以下几点功能:
1. 文字能上下滚动(自动)
2. 能有点击事件
3. 貌似没了~~~
那先看看效果图这里写图片描述

文字的滚动效果实现

首先的话,咱们先把文字画出来吧,用canvas.drawText固然没错,但是首先要解决一个问题就是说怎么让文字上下居中呢?(如果自己有经常用canvas.drawText的话那肯定熟悉)我们的思路是先画矩形,具体请看代码

mRect = new Rect(20, 20, getMeasuredWidth()-20, getMeasuredHeight()-20);
Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();
mY = (mRect.bottom + mRect.top - fontMetrics.bottom - fontMetrics.top) / 2;

其实上面的mY就是我们绘制文字的Y坐标了。
那么然后让文字滚动起来,我这边是通过启动一个计时器,看代码:

@Override
    protected void onDraw(final Canvas canvas) {
        if(data != null){
            if(mY == 0&&!isMove){
                mRect = new Rect(20, 20, getMeasuredWidth()-20, getMeasuredHeight()-20);
                Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();
                mY = (mRect.bottom + mRect.top - fontMetrics.bottom - fontMetrics.top) / 2;
                nY = mY;
            }
            Item item = data.get(mIndex);
            String text = item.getName();
            canvas.drawText(text,mRect.left, nY, textPaint);
            if(!isStart){
                isStart = true;
                Timer timer = new Timer();
                countingDown = mInterval+mDuration;
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        countingDown -=20;
                        if(countingDown<=0) {
                            countingDown = mInterval + mDuration;
                            isMove = true;
                        }
                        if(countingDown<=mInterval-40&&countingDown>0){
                            isMove = false;
                            drawTextStill();
                        }
                        if(isMove) {
                            drawTextMove();
                        }
                    }
                },mInterval,20);
            }
        }
    }
    private void drawTextStill(){
        nY = mY;
        postInvalidate();
    }
    private void drawTextMove(){
        nY -=  getMeasuredHeight()/(mDuration/20);
        if(nY<0){
            mIndex++;
            if(mIndex == data.size())
                mIndex = 0;
            nY = getMeasuredHeight();
        }
        postInvalidate();
    }

点击事件实现

这个就更加简单啦~

@Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (onClickListener != null) {
                    onClickListener.onClick(data.get(mIndex));
                }
                break;
        }
        return true;
    }

然后开放一些其余的接口

/**
     * 设置广告文字的停顿时间
     * */
    public void setIntervalTime(int mInterval) {
        this.mInterval = mInterval;
    }

    /**
     * 设置文字从出现到消失的时长
     * */
    public void setDurationTime(int mDuration) {
        this.mDuration = mDuration;
    }

    /**
     * 设置文字颜色
     * */
    public void setNoticeColor(int mFrontColor) {
        textPaint.setColor(mFrontColor);
    }

全部代码

最后贴一下全部代码,其实就一个自定义控件

public class ENoticeView extends View {
    private String TAG = "Blin ENoticeView";
    private List<Item> data; //显示文字的数据源
    private int mIndex = 0; //当前的数据下标
    private int mDuration = 400; //文字从出现到显示消失的时间
    private int mInterval = 3000; //文字停留在中间的时长切换的间隔
    private boolean isMove = false; //文字是否移动
    private boolean isStart = false; //是否开始
    private int mY = 0; //文字的初始Y坐标
    private int nY = 0; //文字的Y坐标
    private Paint textPaint;
    private final int TEXT_COLOR = 0xff333333;
    private final int TEXT_SIZE = 12;
    private Rect mRect;
    private TimerTask timerTask;

    public ENoticeView(Context context) {
        super(context);
        init();
    }

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

    public ENoticeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init(){
        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setColor(TEXT_COLOR);
        DisplayMetrics metrics =  new DisplayMetrics();
        metrics.setToDefaults();
        textPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,TEXT_SIZE,metrics));
    }

    @Override
    protected void onDraw(final Canvas canvas) {
        if(data != null){
            if(mY == 0&&!isMove){
                mRect = new Rect(20, 20, getMeasuredWidth()-20, getMeasuredHeight()-20);
                Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();
                mY = (mRect.bottom + mRect.top - fontMetrics.bottom - fontMetrics.top) / 2;
                nY = mY;
            }
            Item item = data.get(mIndex);
            String text = item.getName();
            canvas.drawText(text,mRect.left, nY, textPaint);
            if(!isStart){
                isStart = true;
                Timer timer = new Timer();
                countingDown = mInterval+mDuration;
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        countingDown -=20;
                        if(countingDown<=0) {
                            countingDown = mInterval + mDuration;
                            isMove = true;
                        }
                        if(countingDown<=mInterval-40&&countingDown>0){
                            isMove = false;
                            drawTextStill();
                        }
                        if(isMove) {
                            drawTextMove();
                        }
                    }
                },mInterval,20);
            }
        }
    }
    private long countingDown = 0;

    private void drawTextStill(){
        nY = mY;
        postInvalidate();
    }
    private void drawTextMove(){
        nY -=  getMeasuredHeight()/(mDuration/20);
        if(nY<0){
            mIndex++;
            if(mIndex == data.size())
                mIndex = 0;
            nY = getMeasuredHeight();
        }
        postInvalidate();
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (onClickListener != null) {
                    onClickListener.onClick(data.get(mIndex));
                }
                break;
        }
        return true;
    }
    public interface OnNoticeClickListener {
        public void onClick(Item item);
    }

    private OnNoticeClickListener onClickListener;

    public void setOnNoticeClickListener(OnNoticeClickListener onClickListener) {
        this.onClickListener = onClickListener;
    }
    /**
     * 设置数据源
     * */
    public void setData(List<Item> data) {
        this.data = data;
        invalidate();
    }
    /**
     * 设置数据源,并且重置
     * */
    public void setData(List<Item> data,boolean isReStart) {
        this.data = data;
        if (isReStart)
            mIndex = 0;
        invalidate();
    }

    /**
     * 设置广告文字的停顿时间
     * */
    public void setIntervalTime(int mInterval) {
        this.mInterval = mInterval;
    }

    /**
     * 设置文字从出现到消失的时长
     * */
    public void setDurationTime(int mDuration) {
        this.mDuration = mDuration;
    }

    /**
     * 设置文字颜色
     * */
    public void setNoticeColor(int mFrontColor) {
        textPaint.setColor(mFrontColor);
    }
}

用法

eNoticeView = (ENoticeView) findViewById(R.id.noticeView);
ArrayList<Item> items = new ArrayList<>();
for(int i = 0;i<5;i++){
     Item item = new Item();
     item.setName("比比大哥测试:"+i);
     items.add(item);
}
eNoticeView.setData(items);
eNoticeView.setOnNoticeClickListener(new ENoticeView.OnNoticeClickListener() {
    @Override
    public void onClick(Item item) {
        Toast.makeText(MainActivity.this,item.getName(),Toast.LENGTH_SHORT).show();
        }
});

总结

东西真的很简单,绘制的东西也非常少,难点在于上面的计时器绘制循环,这边需要仔细思考下的,然后控制一下子线程,经过测试应该没有什么大问题哈,唯一可能存在的问题就是如果你在RecyclerView中用到的话,如果控件被释放了,要怎么去取消timerTask的问题喽,思考一下呗。

传送门:https://github.com/Blincheng/ENoticeView2

最后可以去看看另一种实现思路【Android】App首页上下滚动快报控件 通知控件 类似京东快报控件(二)
http://blog.csdn.net/qq_25867141/article/details/54603248

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: calendarview控件Android中自带的一个日历控件,可以展示日历的月份、日期等信息。美柚App是一款备孕怀孕期的助手应用,其中的孕期日历是非常重要的功能之一。通过对比美柚App孕期日历和calendarview控件的属性,可以轻松地仿制出类似的孕期日历功能。 首先,需要修改calendarview控件的样式和颜色,使其更接近美柚App的设计风格。可以通过修改控件的属性和调整资源文件中的样式来实现。 其次,需要添加日期的标注和提示信息,例如月经期、排卵期、预计分娩日期等。该功能可以通过在calendarview中设置特定日期的标记和点击事件来实现。 最后,需要实现在孕期日历中显示当天是否受孕、孕周数、宝宝大小等信息。这需要在代码中进行计算,根据用户输入的信息和当前时间来动态展示相应的信息。可以通过创建一个类来处理计算和展示相关信息的逻辑,并将其与calendarview控件关联起来。 综上所述,仿制美柚App的孕期日历需要对calendarview控件的样式、功能和计算逻辑进行修改和扩展。通过合理地利用已有的控件和资源,可以轻松地实现一个类似的应用。 ### 回答2: calendarview控件Android开发中常用的日历选择控件,它可以以日历的形式展示日期,并允许用户通过手势或点击选择日期,常见的属性包括日期的显示格式、日期的范围、当前选中日期等。在美柚app中,有一个孕期日历模块,用户可以通过这个模块记录自己的孕期信息,包括日期、孕周、体重、胎动等,通过分析这些信息,可以为用户提供个性化的孕期建议和咨询服务。 在实现类似美柚app孕期日历的功能时,我们可以使用calendarview控件来展示日期,并通过自定义布局和样式来实现不同的日期显示效果。比如,为了突出当前选中日期,我们可以通过设置选中日期的背景色或添加高亮边框来实现。为了支持选择日期范围,我们可以通过设置日期的最小值和最大值来限制用户选择的日期。同时,为了展示孕周和其他信息,我们可以自定义日期的布局,将孕周等信息与日期一起展示,从而更方便用户使用和理解。 除了上述基本的属性和布局方案,我们还可以通过添加动画效果、支持多语言等方式优化用户体验,从而让我们的控件更加实用和易用。总之,calendarview控件在实现类似美柚app孕期日历的功能时,具有很大的优势和灵活性,在开发中需要根据实际需求进行具体的调整和优化,以达到最佳的用户体验和效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值