Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >自定义视图动画比自定义SurfaceView动画更平滑?

自定义视图动画比自定义SurfaceView动画更平滑?
EN

Stack Overflow用户
提问于 2016-04-01 12:46:53
回答 2查看 595关注 0票数 0

我已经开发了类似的实现来测试我是否应该使用视图或SurfaceView。我实现了视图,如下所示

代码语言:javascript
运行
AI代码解释
复制
public class TimerView extends View {

    private Paint mPiePaint;
    private RectF mShadowBounds;
    private float diameter;

    int startCount = 0;
    private PanelThread thread;

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

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

    public TimerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(VERSION_CODES.LOLLIPOP)
    public TimerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPiePaint.setStyle(Paint.Style.FILL);
        mPiePaint.setColor(0xff000000);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        // Account for padding
        float xpad = (float)(getPaddingLeft() + getPaddingRight());
        float ypad = (float)(getPaddingTop() + getPaddingBottom());

        float ww = (float)w - xpad;
        float hh = (float)h - ypad;

        // Figure out how big we can make the pie.
        diameter = Math.min(ww, hh);
        mShadowBounds = new RectF(0, 0, diameter, diameter);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (startCount == 360) startCount= 0;
        canvas.drawArc(mShadowBounds,
                0, startCount, true, mPiePaint);
        invalidate();
        startCount++;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
        int w = resolveSizeAndState(minw, widthMeasureSpec, 1);
        int h = resolveSizeAndState(MeasureSpec.getSize(w), heightMeasureSpec, 0);
        setMeasuredDimension(w, h);
    }

}

我实现了我的Surface View,如下

代码语言:javascript
运行
AI代码解释
复制
public class TimerSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private Paint mPiePaint;
    private RectF mShadowBounds;
    private float diameter;

    int startCount = 0;
    private PanelThread thread;

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

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

    public TimerSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(VERSION_CODES.LOLLIPOP)
    public TimerSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        getHolder().addCallback(this);
        mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPiePaint.setStyle(Paint.Style.FILL);
        mPiePaint.setColor(0xff000000);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        // Account for padding
        float xpad = (float)(getPaddingLeft() + getPaddingRight());
        float ypad = (float)(getPaddingTop() + getPaddingBottom());

        float ww = (float)w - xpad;
        float hh = (float)h - ypad;

        // Figure out how big we can make the pie.
        diameter = Math.min(ww, hh);
        mShadowBounds = new RectF(0, 0, diameter, diameter);

    }

    protected void drawSomething(Canvas canvas) {
        canvas.drawColor(0xFFEEEEEE);

        if (startCount == 360) startCount= 0;
        canvas.drawArc(mShadowBounds,
                0, startCount, true, mPiePaint);
        startCount++;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
        int w = resolveSizeAndState(minw, widthMeasureSpec, 1);
        int h = resolveSizeAndState(MeasureSpec.getSize(w), heightMeasureSpec, 0);
        setMeasuredDimension(w, h);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        setWillNotDraw(false); //Allows us to use invalidate() to call onDraw()
        thread = new PanelThread(getHolder(), this); //Start the thread that
        thread.setRunning(true);                     //will make calls to
        thread.start();                              //onDraw()
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // tell the thread to shut down and wait for it to finish
        // this is a clean shutdown
        boolean retry = true;
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                // try again shutting down the thread
            }
        }
    }
}

和SurfaceView线程如下所示

代码语言:javascript
运行
AI代码解释
复制
class PanelThread extends Thread {
    private SurfaceHolder surfaceHolder;
    private TimerSurfaceView panel;
    private boolean starRunning = false;


    public PanelThread(SurfaceHolder surfaceHolder, TimerSurfaceView panel) {
        this.surfaceHolder = surfaceHolder;
        this.panel = panel;
    }


    public void setRunning(boolean run) { //Allow us to stop the thread
        starRunning = run;
    }


    @Override
    public void run() {
        Canvas c;
        while (starRunning) {     //When setRunning(false) occurs, starRunning is
            c = null;      //set to false and loop ends, stopping thread
            try {
                c = surfaceHolder.lockCanvas(null);
                synchronized (surfaceHolder) {
                    //Insert methods to modify positions of items in onDraw()
                    panel.drawSomething(c);
                }
            } finally {
                if (c != null) {
                    surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
}

结果显示,如https://www.youtube.com/watch?v=s9craUgY3I4中所示,自定义视图(TimerView)比曲面视图更平滑。根据http://stackoverflow.com/questions/23893266/why-surfaceview-is-slower-than-a-custom-view的说法,SurfaceView虽然速度较慢,但应该更流畅。

会不会是因为在SurfaceView中,我需要重新着色来擦除之前的draw canvas.drawColor(0xFFEEEEEE); on drawSomething函数?有没有一种方法可以消除重新着色的需要,就像我在TimerView中所做的那样,我只是在onDrawinvalidate()

我面临的另一个问题是,当应用程序转到后台并返回时,TimerSurfaceView的drawSomthing将收到一个空画布,而TimerView onDraw()不会失效,动画只是停止。我需要做些什么才能让它继续保持原样?

EN

回答 2

Stack Overflow用户

发布于 2016-04-01 18:03:10

正如我在回答中提到的--对你链接到的问题进行评论:

渲染到SurfaceView的

Canvas不是硬件加速的,而渲染到普通视图的Canvas是硬件加速的。

随着显示像素数的增加(由于小型设备上4K显示器的不可避免的驱动),软件渲染变得更慢。CPU性能和内存带宽的增加将抵消这一影响,但它在某些设备上表现不佳。

你可以通过各种方式来弥补这一点,例如using setFixedSize() to limit the pixel count,但硬件加速渲染通常是一种更好的方法。

如果你的帧率受到CPU的限制,那么任何想要使用同一个CPU核心的东西都会导致jank。您可以将SurfaceView渲染器放在单独的线程中,这一事实很有帮助,但如果您正在突破设备的限制,那么这就无关紧要了。显示正在以一定的速率更新,如果您不能始终满足截止日期,那么您的动画将不会流畅。(其他一些想法可以在this appendix中找到。)

票数 1
EN

Stack Overflow用户

发布于 2016-07-29 12:01:29

Android开发人员说,你应该在主线程上做所有的动画,因为他们的框架在UI工作中不能很好地工作

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36356748

复制
相关文章
WiFi 6路由器和WiFi 5路由器有什么区别
随着新一代无线通信标准的普及和生产成本下降,支持WiFi 6标准的网关/路由器近两年得到越来越广泛的应用。WiFi 6路由器相比前一代路由器有什么提升呢?我们是不是一定要更换WiFi 6路由器呢?本篇文章就为大家简单介绍一下。
智慧物联小马
2022/06/09
2.1K0
WiFi 6路由器和WiFi 5路由器有什么区别
【路由器外网映射】腾达A63路由器设置虚拟服务器
一:登陆腾达路由器后台(192.168.0.1)后再高级功能,选择虚拟服务器.如下图:
凯哥Java
2022/12/16
1.7K0
【路由器外网映射】腾达A63路由器设置虚拟服务器
k2路由器刷系统
1)断开电源 2)按住reset键,然后插上电源 3)等待十秒,松开 4)用网线将k2的lan口接入电脑网口 5)访问192.168.1.1,进入breed控制台
治电小白菜
2020/08/25
1.3K0
k2路由器刷系统
链路状态路由协议 OSPF (一)
本章将会学习链路状态路由协议OSPF,理解OSPF的基本概念,工作原理,掌握OSPF配置基本命令
网络豆
2022/11/20
6800
链路状态路由协议 OSPF (一)
烽火2640路由器命令行手册-05-路由器配置命令
使用auto-summary命令激活自动路由汇总功能,no auto-summary命令则关闭自动路由 汇总功能。
landv
2018/12/17
2.4K0
链路状态路由协议 OSPF (三)
广播网络中,两台路由器运行OSPF路由协议(实际可能有多台路由器,这里以两台路由器为例)
网络豆
2022/11/20
3800
链路状态路由协议 OSPF (三)
链路状态路由协议 OSPF (二)
因为运行OSPF的路由器要了解每条链路是连接在那个路由器上的,因此,就需要有一个唯一的标识来标记OSPF网络中的路由器,这个唯一标识称为router ID。
网络豆
2022/11/20
5390
链路状态路由协议 OSPF (二)
telnet登陆路由器。。。「建议收藏」
登陆路由有两种方式。一种是console,还有一种是使用telnet,由于我电脑是win7,不支持console。也懒得装软件,就使用telnent为例。
全栈程序员站长
2022/07/08
1.7K0
telnet登陆路由器。。。「建议收藏」
面试官:重点描述一下三大路由协议对IPv6的支持
(1)为了支持IPv6路由的处理计算,ISIS新增了两个TLV和一个新的NLPID
Ponnie
2021/07/29
1.7K0
移植python到小米路由器记录。
最近抢了一个小米路由器,研究了一下,总的来说现在看起来功能还很少。现在比较有用的功能就是,远程下载功能,支持迅雷,电驴等,不过现在看电影啥的都是直接在线看的,基本上也很少用。检测连接的智能设备,这个功能可以随时查看是否有人曾网,当然也可以用来在远程监控家里都有谁在用路由器。以后应该会有更多的功能扩展,不过这应该是一个漫长的过程,我先自己弄点东西上去玩玩,首先把常用的python移植上去。
py3study
2020/01/08
2.5K0
h3c路由器telnet配置命令_华三路由器telnet配置
主机的配置就略咯,不可能真让你抄作业吧(不会吧不会吧,都暗示这么明白了,不会还有人不会抄作业吧)
全栈程序员站长
2022/11/09
4.6K0
h3c路由器telnet配置命令_华三路由器telnet配置
TCP/IP之路由算法路由算法的分类链路状态路由算法距离向量(Distance Vector)路由算法层次路由例: 路由器1d的转发表设置
网络层的重要功能就是路由和转发。而路由是根据路由器根据所维护的路由表进行路由选择。所以,如果创建和更新转发表就是一个很重要的问题。通常,在路由时,我们总是选取所需代价最小的一条路由。
desperate633
2018/08/22
2.6K0
TCP/IP之路由算法路由算法的分类链路状态路由算法距离向量(Distance Vector)路由算法层次路由例: 路由器1d的转发表设置
小米AC2100路由器刷机教程
之前家中免费的电信宽带免费升级到500M后,原有的360 P1百兆路由器很明显无法提供500M的网络速度,然后购买了一款小米AC2100路由器。
KINDYEAR
2022/07/12
10K1
小米AC2100路由器刷机教程
h3c路由器的配置命令_华三路由器清除配置命令
****************************************************************************** * Copyright (c) 2004-2017 New H3C Technologies Co., Ltd. All rights reserved.* * Without the owner’s prior written consent, * * no decompiling or reverse-engineering shall be allowed. * ******************************************************************************
全栈程序员站长
2022/11/02
1.7K0
h3c路由器的配置命令_华三路由器清除配置命令
BGP实验“杂烩”:IBGP、EBGP、路由策略、路由聚合、链路备份
(3).路由器之间中继链路使用接口地址为:192.168.0.0/16,已经有基础配置。
网络技术联盟站
2023/03/01
7960
BGP实验“杂烩”:IBGP、EBGP、路由策略、路由聚合、链路备份
如何利用智能路由器实现智慧路内停车方案
随着城市化的推进,各城市的主要路段人流车流量日益加大,周边停车位资源也愈加紧张,“停车难”的问题越来越受到关注。针对优化城市停车管理,佰马通过智能路由器配套构建智慧路内停车方案,促进无人值守电子收费路段的车位利用率提升,加强停车秩序规范,缓解路面停车压力,提高城市管理效率。
智慧物联小马
2022/06/15
3750
如何利用智能路由器实现智慧路内停车方案
点击加载更多

相似问题

如何将状态从reach路由器传递到链路

23

在Gatsby中用reach路由器嵌套生成链路的路由

11

使用Reach路由器导航到404路由

317

用params响应路由器链路

10

用路由器链路发送数据

24
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档