跑马灯状态获取(停止后自动隐藏,用于广告推送等)

来源:互联网 发布:二手交易管理系统源码 编辑:程序博客网 时间:2024/05/23 11:45

继之前一篇的推送广告需求,需要广告播放3次后自动消失。

因此需要监控TextView的Marquee的状态,在Marquee  stop之后隐藏TextView。

查看了文档,TextView并没有提供一个获取跑马灯状态的接口。只能自己想办法了。


这里先放出代码,各位看官如果需要,可以直接下代码,因为本人文笔实在...

https://github.com/HangminTian/MarqueueDemo

争取慢慢改进,提升文章可读性


Marquee是TextView的内部类,点到TextView源码中找到它。

下面列出和需求相关的重要成员

跑马灯状态标识,3个byte类型。

private static final byte MARQUEE_STOPPED = 0x0;private static final byte MARQUEE_STARTING = 0x1;private static final byte MARQUEE_RUNNING = 0x2;


默认重播次数为3,刚刚好是需求次数。省的我自己设置了。

mStatus是我们想要的东西,它记录了marquee当前的状态。

private int mMarqueeRepeatLimit = 3;private byte mStatus = MARQUEE_STOPPED;

接下来两个跟需求没什么关系,但是我们可以拿来做做文章,订制我们自己需要的效果。

比如改变一下速度、等待时间。

private static final int MARQUEE_DELAY = 1200;private static final int MARQUEE_RESTART_DELAY = 1200;



目的很明确,就是要获取TextView的私有内部类Marquee的mStatus值,可以用反射啊


然后反射代码是这样的(马克,2016/9/22,兼容AppCompatTextView,已经同步更新到github):

private void getFiled(){        Class<?> mTextViewClass = mTextView.getClass();        if(mTextViewClass != TextView.class){            mTextViewClass = mTextViewClass.getSuperclass();        }        Field filedMarquee = null;        try {            filedMarquee = mTextViewClass.getDeclaredField("mMarquee");        } catch (NoSuchFieldException e) {            e.printStackTrace();        }        if(filedMarquee == null){            return;        }        filedMarquee.setAccessible(true);        try {            mMarquee = filedMarquee.get(mTextView);        } catch (IllegalAccessException e) {            e.printStackTrace();        }        if(mMarquee == null){            return;        }        Class<?> mMarqueeClass = mMarquee.getClass();        try {            fieldStatus = mMarqueeClass.getDeclaredField("mStatus");        } catch (NoSuchFieldException e) {            e.printStackTrace();        }        if(fieldStatus == null){            return;        }        fieldStatus.setAccessible(true);    }    public void checkStop(){        if(fieldStatus == null){            getFiled();        }        if(fieldStatus == null){            Log.d(TAG, "fieldStatus == null");            return;        }        Byte mStatus = -1;        try {            mStatus = (Byte) fieldStatus.get(mMarquee);        } catch (IllegalAccessException e) {            e.printStackTrace();        }    }


这样,我们就获得了mStatus的值,但是我们要知道它何时被置成了stop(0x0),

这里我采用的轮询,每1秒去检查一次,虽然这个办法不是很靠谱,但暂时也是个办法吧。

有好方法的大神希望提供一下思路。


用一个Handler负责去检查marquee是否已经停止。

 final Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            if (msg.what == CHECK_MARQUE_STOPED) {                checkStop();            }            super.handleMessage(msg);        }    };



在Activity初始化的时候,用一个Timer定时去启动这个handler,以保证TextView的内部全部已经加载完成。

mTimer = new Timer();        mTimer.schedule(new TimerTask() {            @Override            public void run() {                mHandler.sendEmptyMessage(CHECK_MARQUE_STOPED);            }        }, 2000);



在checkStop中,每当检查到还没stop的时候,继续进行检查,如果已经stop,则隐藏TextView,并终止检查。

    private void getFiled(){        Class<?> mTextViewClass = mTextView.getClass();        if(mTextViewClass != TextView.class){            mTextViewClass = mTextViewClass.getSuperclass();        }        Field filedMarquee = null;        try {            filedMarquee = mTextViewClass.getDeclaredField("mMarquee");        } catch (NoSuchFieldException e) {            e.printStackTrace();        }        if(filedMarquee == null){            return;        }        filedMarquee.setAccessible(true);        try {            mMarquee = filedMarquee.get(mTextView);        } catch (IllegalAccessException e) {            e.printStackTrace();        }        if(mMarquee == null){            return;        }        Class<?> mMarqueeClass = mMarquee.getClass();        try {            fieldStatus = mMarqueeClass.getDeclaredField("mStatus");        } catch (NoSuchFieldException e) {            e.printStackTrace();        }        if(fieldStatus == null){            return;        }        fieldStatus.setAccessible(true);    }    public void checkStop(){        if(fieldStatus == null){            getFiled();        }        if(fieldStatus == null){            Log.d(TAG, "fieldStatus == null");            return;        }                Byte mStatus = -1;        try {            mStatus = (Byte) fieldStatus.get(mMarquee);        } catch (IllegalAccessException e) {            e.printStackTrace();        }        Log.d(TAG, "mStatus = "+mStatus);        if(mStatus == MARQUEE_STOPPED){            mTextView.setVisibility(View.GONE);            return;        }        mTimer.schedule(new TimerTask() {            @Override            public void run() {                mHandler.sendEmptyMessage(CHECK_MARQUE_STOPED);            }        }, 1000);    }


0 0
原创粉丝点击