首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >自定义视图动画比自定义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

复制
相关文章
反应式编程框架设计:如何使得程序调用不阻塞等待
程序在高并发的情况下,程序容易崩溃。主要的原因是:在高并发的情况下,有大量用户请求需要程序计算处理,而目前的处理方式是,为每个用户请求分配一个线程,当程序内部因为访问数据库等原因造成线程阻塞时,线程无法释放去处理其他请求,这样就会早在请求的堆积,不断的消耗资源,最终导致程序的崩溃。
小马哥学JAVA
2023/02/27
7160
反应式编程框架设计:如何使得程序调用不阻塞等待
如何在Python中创建天气警报系统
通过阅读这篇文章,你将学会用Python创建一个天气警报系统,当它预测未来几小时内天空将下雨/下雪时,它会向多个收件人发送一封电子邮件通知。电子邮件通知包含其他信息,如预测的温度和湿度。
HuangWeiAI
2020/12/18
2.7K0
currentHashMap的公平锁,可中断响应,限制等待实例
HashMap是线程非安全的,怎么能线程安全呢,这时候hashtable就出现了,hashmap允许放null,且有且只有一个null,因为不能key不能重复,hashtable不允许放null。
用户9919783
2022/07/26
3950
currentHashMap的公平锁,可中断响应,限制等待实例
Go 中如何关闭 http 响应
当你使用标准http库发起请求时,你得到一个http的响应变量。如果你不读取响应主体,你依旧需要关闭它。注意对于空的响应你也一定要这么做。对于新的Go开发者而言,这个很容易就会忘掉。
王小明_HIT
2021/08/28
1.9K0
Go 中如何关闭 Http 响应
当你使用标准http库发起请求时,你得到一个http的响应变量。如果你不读取响应主体,你依旧需要关闭它。注意对于空的响应你也一定要这么做。对于新的Go开发者而言,这个很容易就会忘掉。
王小明_HIT
2021/09/15
8910
DialoGPT:大规模预训练的对话响应模型
今天给大家介绍的是由微软Yizhe Zhang等人发表在arXiv上的文章”DialoGPT: Large-Scale Generative Pre-training for Conversational Response Generation”,此文已被ACL 2020接收。
DrugAI
2021/02/01
3K0
DialoGPT:大规模预训练的对话响应模型
Prometheus:警报
1、alertmanager.yml文件 global: resolve_timeout: 5m smtp_smarthost: 'smtp.163.com' smtp_from: '13285921108@163.com' smtp_auth_username: '13285921108@163.com' smtp_auth_password: 'xxxxxxxxxx' wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
用户5760343
2020/01/15
5930
[答疑]业务序列图上等待响应怎么画
这样合理不?还是要拆成1.6拆成另一个用例,但是用户对引入系统的期望是反馈xxx结果,拆成两个用例不大恰当
用户6288414
2020/05/25
3790
[答疑]业务序列图上等待响应怎么画
WebDriverIO教程:处理Selenium中的警报和覆盖
在此有关Selenium中警报处理的WebDriverIO教程中,我将向您展示如何在WebDriverIO中处理警报和弹出窗口以及叠加模式。我还将介绍自动化期间将要遇到的各种类型的警报,以及使用WebDriverIO在Selenium中处理警报时需要遵循的关键点。
PHP开发工程师
2021/04/21
6K0
WebDriverIO教程:处理Selenium中的警报和覆盖
SSR长时间等待代理隧道响应的有效解决办法
作为一名专业爬虫代理,我深知在使用SSR(ShadowsocksR)时可能会遇到代理隧道长时间等待响应的情况。这种情况极大地妨碍了爬虫程序的效率和稳定性。在本文中,我将分享一些有效的解决办法,帮助你解决SSR长时间等待代理隧道响应的问题,并提升你的爬虫程序效果。
华科云商小彭
2023/08/11
5640
SSR长时间等待代理隧道响应的有效解决办法
WebDriverIO教程:处理Selenium中的警报和覆盖
在此有关Selenium中警报处理的WebDriverIO教程中,我将向您展示如何在WebDriverIO中处理警报和弹出窗口以及叠加模式。我还将介绍自动化期间将要遇到的各种类型的警报,以及使用WebDriverIO在Selenium中处理警报时需要遵循的关键点。
用户7466307
2020/07/20
6.3K0
WebDriverIO教程:处理Selenium中的警报和覆盖
Actframework中如何灵活控制JSON响应
@DiamondFsd 昨天写了一篇关于如何在Spring MVC中灵活控制JSON返回的博客,其中@JSON注解的思路和我在actframework的处理方式非常相似。 刚好昨天把actframework放上码云了,就这个话题写下 如何在ActFramework中控制JSON返回 首先是资源和服务。我将就@DiamondFsd的article的例子来做讲解 @Entity("article") public class Article extends MorphiaAdaptiveRecord<Artic
老码农
2018/06/27
9850
VC如何获取对话框中控件的坐标
VC如何获取对话框中控件的坐标 GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置。 GetClientRect取得窗口客户区(不包括非客户区)在客户区坐标系下的RECT坐标,可以得到窗口的大小,而不能得到相对屏幕的位置,它的top和left都为0,right和botton是宽和高,因为这个矩阵是在客户区坐标系下(相对于窗口客户区的左上角)的。   ClientToScreen把客户区坐标系下的RECT坐标转换为屏
_gongluck
2018/03/08
2.6K0
ObjectARX中反应器的使用
ObjectARX中反应器的使用 反应器机制是观察者模式(设计模式)的一种实现,在该机制下,有事件通知者和事件接收者,负责接收事件的称为反应器 反应器列表:在反应器可以从通知者处接收消息之前,必须显式地将反应器添加到通知者的反应器列表中。 反应器部分类继承关系 种类:
用户3519280
2023/07/24
4150
ajax提交等待服务器响应友好提示信息的实现
众所周知,在客户端向服务器发送AJAX请求时,会有一个等待服务器响应的过程,在网络环境好而且服务器负荷小的时候,业务逻辑不大太复杂的请求可能一下子就处理完并返回响应结果了,但当网络环境不理想或请求涉及到大量的运算时,服务器响应的时间或许就会比较漫长了,特别对于正在操作,正期待操作结果的用户来说,这段等待时候是无比的漫长,如果你没有过这样的操作体验,你回想一下约会时别人迟到的时候或有急事出门时在公交站苦苦等车的滋味,相信你就能感同身受了,而让用户忍受如此煎熬,对于强调用户体验的Web2.0时代,是大忌,是追求“为用户创造价值,让用户享受电子商务所带来的方便快捷”为宗旨的我所不能接受的。虽然,我不能改变客观环境因素带来的长响应时间,但我可以告诉用户系统正在做什么,让他们感受到,系统很在乎他们的感受,并愿意亲切地和他们交流的,而不是传统的软件那样,死板、霸道、冷冰冰的,好了,不多说大道理了,看看我的做法吧。
风柏杨4711
2021/03/15
2.6K0
语音交互中的“等待体验”研究
回顾人机交互发展史,人类先后经历了基于命令行的CLI 时代,基于鼠标键盘的GUI时代,基于触摸的初级NUI时代。后面每一个阶段比前一个阶段更自然,学习成本更低,综合效率更高。 进入AI时代,人工智能给
前朝楚水
2018/04/04
2K0
语音交互中的“等待体验”研究
有效的云安全警报
该文介绍了如何设置有效的云安全警报系统,包括避免“噪音”,设置准确度,消除错误警报,简化安装过程等方面。
用户1204935
2018/01/05
1.7K0
有效的云安全警报
直接内存回收中的等待队列
在直接内存回收过程中,有可能会造成当前需要分配内存的进程被加入一个等待队列,当整个node的空闲页数量满足要求时,由kswapd唤醒它重新获取内存。这个等待队列头就是node结点描述符pgdat中的pfmemalloc_wait。如果当前进程加入到了pgdat->pfmemalloc_wait这个等待队列中,那么进程就不会进行直接内存回收,而是由kswapd唤醒后直接进行内存分配。
233333
2020/04/13
1.6K0
如何在gin中获取响应体内容?
实现思路: 对gin的responseWriter进行包装, 每次写往请求方写响应数据的时候,将响应数据返回出去。step1: 定义一个新的CustomResponseWriter,通过组合方式持有一个gin.ResponseWriter和response body缓存。type CustomResponseWriter struct { gin.ResponseWriter body *bytes.Buffer}func (w CustomResponseWriter) Write(b []byt
Johns
2021/04/10
11.8K0
如何在gin中获取响应体内容?
点击加载更多

相似问题

路由不匹配反应路由器(-redux)

25

嵌套反应路由器:不匹配任何路由

22

反应-路由器在有效路由上不匹配

34

一些不匹配的路由-路由器4

13

反应路由器-没有匹配的任何路由

14
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

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

洞察 腾讯核心技术

剖析业界实践案例

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