RN中实现类似Android中的帧动画及坑

一、前言

在Android中实现帧动画很简单,定义一个animation-list就可以直接使用了,例如:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false" >
    <item
        android:drawable="@drawable/custom_clock_time_01"
        android:duration="1000">
    </item>
    <item
        android:drawable="@drawable/custom_clock_time_02"
        android:duration="1000">
    </item>
    <item
        android:drawable="@drawable/custom_clock_time_03"
        android:duration="1000">
    </item>
    <item
        android:drawable="@drawable/custom_clock_time_04"
        android:duration="1000">
    </item>

二、实现

但是在RN中应该是没有这种简单的方法吧,不过也可以实现类似的效果,原理就是定义一个数组把帧动画需要的那些图片放入数组汇总,然后使用一个定时器setInterval不断的展示这几张图片,就可以了。

实现CockView组件

import React, {Component} from 'react';
import {
    Platform,
    StyleSheet,
    Text,
    View,
    Image
} from 'react-native';

var LoadingImgs = [
    require('./img/custom_clock_time_01.png'),
    require('./img/custom_clock_time_02.png'),
    require('./img/custom_clock_time_03.png'),
    require('./img/custom_clock_time_04.png'),
];

export default class CockView extends Component {
    //设置默认属性
    static defaultProps = {
        time: 60
    }

    constructor(props) {
        super(props);
        console.log("constructor==")
        this.state = {
            loadImgIndex: 0,
            time: props.time
        }
    }

    componentDidMount() {
        if (this.timer === undefined) {
            this.timer = setInterval(() => {
                let i = this.state.loadImgIndex + 1;
                i = i % LoadingImgs.length;
                this.setState({
                    loadImgIndex: i,
                    time: this.state.time - 1
                })
                if (this.state.time === 0) {
                    clearInterval(this.timer);
                }
                console.log("i==",i)
            }, 1000);
        }
    }

    componentWillUnmount() {
        this.timer && clearInterval(this.timer);
    }

    render() {
        return (
            <View style={{
                justifyContent: 'center',
                alignItems: 'center',
                flexDirection: 'row'
            }}>
                <View style={{marginLeft: 20}}>
                    <Text style={{fontSize: 30}}>{this.state.time} 秒</Text>
                </View>
            </View>
        )
    }
}

最后在其他地方使用这个组件就可以了, time是指定倒计时的时间

<CockView time={10}/>

三、问题

但是有个小bug,就是刚进入界面后,第一次循环,图片会闪烁,这是怎么回事呢?这个问题纠结了我好久,无意之间我直接使用Image控件一个一个加载每个图片,他就不会闪烁了,

render() {
        return (
            <View style={{
                justifyContent: 'center',
                alignItems: 'center',
            }}>
                <Image style={{width: 80, height: 80}} 
                    source={require('./img/custom_clock_time_01.png')} />
                <Image style={{width: 80, height: 80}}
                    source={require('./img/custom_clock_time_02.png')} />
                <Image style={{width: 80, height: 80}}
                    source={require('./img/custom_clock_time_03.png')} />
                <Image style={{width: 80, height: 80}}
                source={require('./img/custom_clock_time_04.png')} />
                <Image style={{width: 80, height: 80}}
                       source={LoadingImgs[this.state.loadImgIndex]} />
                <View style={{marginLeft: 20}}>
                    <Text style={{fontSize: 30}}>{this.state.time} 秒</Text>
                </View>
            </View>
        )
    }

从这我估计是第一次循环的时候,这四张都还没有缓存,所有有闪烁现象。

问题找到了,但是我页面中不可能把这四张都显示出来吧,有没有像Android中,只加载控件却不显示的方法呢?经过我多方查找貌似没有。难道这个没有问题了?好在我突然想到加载这四张图片,但是把这个Image的宽高都设置为0试一试,果然可以了

render() {
        return (
            <View style={{
                justifyContent: 'center',
                alignItems: 'center',
                flexDirection: 'row'
            }}>
                <Image style={{width: 0, height: 0}} 
                    source={require('./img/custom_clock_time_01.png')} />
                <Image style={{width: 0, height: 0}}
                    source={require('./img/custom_clock_time_02.png')} />
                <Image style={{width: 0, height: 0}}
                    source={require('./img/custom_clock_time_03.png')} />
                <Image style={{width: 0, height: 0}}
                source={require('./img/custom_clock_time_04.png')} />
                <Image style={{width: 80, height: 80}}
                       source={LoadingImgs[this.state.loadImgIndex]} />
                <View style={{marginLeft: 20}}>
                    <Text style={{fontSize: 30}}>{this.state.time} 秒</Text>
                </View>
            </View>
        )
    }

哈哈,虽然有点投机取巧,先这么用吧!

源代码地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 人都会普遍高估自己的认知水平,容易把集体知识,和环境知识,都当作是自己的。比如,对待日常生活中的,抽水马桶,锁芯的...
    Lucas的学习笔记阅读 1,427评论 0 0
  • 幼儿教师成长课程陪伴我们小青椒走过了十二讲,感谢各位主讲老师助力乡村教育,为我们农村幼儿教师带来新理念,感谢互加计...
    陈细冬阅读 2,241评论 0 0
  • 倒推法:K12小学初中高中培训 学生--家长--老师 所以老师是重点 用户生命周期:
    流浪思维记阅读 1,054评论 0 0
  • 如果途中不曾相遇,你会不会是我不远处的守侯。 今生最缠绵而温柔的爱恋,我将会错过这一世纪。 在你的世界里是否我就是...
    田萍阅读 2,773评论 0 3

友情链接更多精彩内容