Android自定义内容滚动控件

效果图:
效果图
源码:

public class RollView extends FrameLayout {


    private static final int DEFAULTTEXTSIZE = 16;
    private static final int DEFAULTTEXTHEIGHT = 72;

    private List<?> contents = new LinkedList<>();

    private float textSize;
    private int textColor = Color.BLACK;
    //当前显示内容在集合中的下标
    private int curIndex = -1;
    //下一个显示的下标
    private TextView curText;
    private TextView nextText;
    private int hSize;
    private int wSize;
    private TranslateAnimation outAnim;
    private TranslateAnimation inAnim;
    //是否执行动画中
    private boolean isAnimationing = false;
    private onItemClickListener listener;


    private MyHandler handler = new MyHandler(this);

    public RollView(Context context) {
        this(context, null);
    }

    public RollView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void init(Context context, AttributeSet attrs) {


        View view = LayoutInflater.from(context).inflate(R.layout.custom_rollview_layout, this);


        curText = ((TextView) view.findViewById(R.id.curText));
        nextText = ((TextView) view.findViewById(R.id.nextText));

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RollView);
        float tmpTextSize = ta.getInteger(R.styleable.RollView_rollSize, DEFAULTTEXTSIZE);
        textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tmpTextSize, getResources().getDisplayMetrics());

        int colorRes = ta.getResourceId(R.styleable.RollView_rollColor, -1);
        int colorRes2 = ta.getColor(R.styleable.RollView_rollColor, -1);

        curText.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //如果是执行动画中,就不响应点击事件
                if (isAnimationing) {
                    return;
                } else {
                    if (listener != null) {
                        listener.onClick(curIndex);
                    }
                }
            }
        });

        if (colorRes != -1) {
            textColor = colorRes;
        } else if (colorRes2 != -1) {
            textColor = colorRes2;
        }

        curText.setTextSize(textSize);
        curText.setTextColor(textColor);

        nextText.setTextSize(textSize);
        nextText.setTextColor(textColor);

        ta.recycle();

    }

    public void setListener(onItemClickListener listener) {
        this.listener = listener;
    }

    /**
     * 可以是自定义类型,只需要重新toString() 方法
     * @param contents
     */
    public void setObjContents(List<?> contents) {
        if (contents == null || contents.size() == 0) {
            return;
        }
        this.contents.clear();
        List<String> list = new LinkedList<>();
        for (Object content : contents) {
            list.add(content.toString());
        }
        setContents(list);
    }

    public void setContents(List<String> contents) {
        if (contents == null || contents.size() == 0) {
            return;
        }
        this.contents = contents;
        initData();
    }

    private void initData() {
        curIndex = 0;
        if (contents.size() > 0) {
            curText.setText(contents.get(0).toString());
        }
        if (contents.size() > 1) {
            nextText.setText(contents.get(1).toString());
        }
    }

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

        int wMode = MeasureSpec.getMode(widthMeasureSpec);
        int hMode = MeasureSpec.getMode(heightMeasureSpec);

        hSize = MeasureSpec.getSize(heightMeasureSpec);
        wSize = MeasureSpec.getSize(widthMeasureSpec);

        switch (hMode) {
            case MeasureSpec.EXACTLY:
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                hSize = DEFAULTTEXTHEIGHT;
                break;
        }
        setMeasuredDimension(wSize, hSize);


        outAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -hSize);
        //动画结束时,将控件还原到初始化状态,必须设置这个
        outAnim.setFillEnabled(true);
        outAnim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                isAnimationing = true;
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                isAnimationing = false;
                curIndex++;
                curIndex = curIndex % contents.size();//滚动到最后一条数据了,下一条显示第一条数据
                int nextIndex = (curIndex + 1) % contents.size();//获取nextText 需要显示的下一条数据的下标


                /**
                 * 这里的含义是:动画结束后,控件还原到初始化状态,
                 * curText 就需要显示滚动后的 nextText 的内容,起到界面没有视觉差
                 * nextText 就需要显示,下下条数据,为了下次滚动做准备
                 */
                curText.setText(contents.get(curIndex).toString());
                nextText.setText(contents.get(nextIndex).toString());

                //动画结束后,延迟3秒继续滚动
                handler.sendEmptyMessageDelayed(0, 2000);

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        outAnim.setDuration(1000);
        inAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, hSize, Animation.ABSOLUTE, 0);
        inAnim.setFillEnabled(true);
        inAnim.setDuration(1000);


    }

    /**
     * 开始滚动,数量必须大于1才会滚动,每3秒滚动一次
     */
    public void startRoll() {
        if (contents.isEmpty() || contents.size() == 1) {
            return;
        }
        handler.sendEmptyMessageDelayed(0, 2000);
    }

    private void roll() {
        if (isAnimationing) {
            return;
        }
        curText.startAnimation(outAnim);
        nextText.startAnimation(inAnim);
    }

    private static class MyHandler extends Handler {

        private WeakReference<RollView> weakReference;

        public MyHandler(RollView rollView) {
            this.weakReference = new WeakReference<>(rollView);
        }

        @Override
        public void handleMessage(Message msg) {
            RollView rollView = weakReference.get();
            if (rollView == null) {
                return;
            }

            rollView.roll();

        }
    }

    public interface onItemClickListener {

        /**
         * 这里也可以用泛型,返回当前显示的自定义数据,为了简单,这里就只返回当前点击的位置
         * @param position
         */
        void onClick(int position);
    }


}

自定义的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textContent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <TextView
        android:id="@+id/nextText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_vertical"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:text="nextText"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_16" />


    <TextView
        android:id="@+id/curText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_vertical"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:text="curText"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_16" />


</FrameLayout>

自定义属性:

 <declare-styleable name="RollView">

        <attr name="rollSize" format="integer" />
        <attr name="rollColor" format="reference|color" />

    </declare-styleable>

使用:

<RollView
    android:id="@+id/rollView"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_56"
    android:background="@color/white"
    android:paddingLeft="@dimen/dp_20"
    app:rollSize="20" />

代码:

List<String> contents = new LinkedList<>();
contents.add("lingtao");
contents.add("lingtao1");
contents.add("lingtao2");
contents.add("lingtao3");
rollView.setContents(contents);
rollView.setListener(new RollView.onItemClickListener() {
    @Override
    public void onClick(int position) {
        LogUtils.d("TestActivity_log", "onClick: " + contents.get(position));
    }
});
rollView.startRoll();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值