尽管在任何地方都使用RGBA_8888,但颜色条带和渐变的人工制品

Tre*_*vor 26 android colors surfaceview bit-depth

我知道色带是一个问题的老栗子,之前已经讨论了很多次提供了各种解决方案(基本上归结为使用32位,或使用抖动).事实上不久前我问过并随后回答了我自己的问题.当时,我还以为我把在回答这个问题的解决方案(这是应用setFormat(PixelFormat.RGBA_8888)Window,也给Holder在的情况下SurfaceView),在我的很好的应用已经解决了这个问题.至少解决方案使得渐变在我当时开发的设备上看起来非常好(很可能是Android 2.2).

我现在正在使用HTC One X(Android 4.0)和华硕Nexus 7(Android 4.1)进行开发.我试图做的是在a的整个区域应用灰色渐变SurfaceView.即使我认为确保包含WindowHolder配置为32位颜色,我得到可怕的绑定工件.事实上,在Nexus 7上,我甚至看到了文物的移动.这不仅发生在SurfaceView当然连续绘制的情况下,而且还发生在View我正常添加的法线中,以便为测试目的绘制完全相同的梯度,这将绘制一次.这些工件的存在方式当然看起来非常糟糕,实际上就像观看信号较差的模拟电视一样.无论是ViewSurfaceView展览完全相同的器物,它们一起四处走动.

我的目的是在整个过程中使用32位,而不是使用抖动.我的印象Window是默认情况下在Android 4.0之前默认为32位.通过应用RGBA_8888SurfaceView我本来期望一切都已经32位全境,从而避免任何文物.

我注意到在SO上还有其他一些问题,人们观察到RGBA_88884.0/4.1平台上似乎不再有效.

这是我的Nexus 7的截图,View顶部和SurfaceView下面都有法线,两者都使用相同的渐变Canvas.当然,它不会像在显示屏上那样显示工件,因此显示此屏幕抓取可能毫无意义.我想强调的是,在Nexus的屏幕上,条带确实看起来很糟糕.编辑:其实,真正的截图没有显示的文物在所有.我在Nexus 7上看到的文物并不是统一的条带; 它看起来很随意.

在此输入图像描述

Activity用于创建以上内容的测试:

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.os.Bundle;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.widget.LinearLayout;

public class GradientTest extends Activity {

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        getWindow().setFormat(PixelFormat.RGBA_8888);
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);      
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
        lp.copyFrom(getWindow().getAttributes());
        lp.format = PixelFormat.RGBA_8888;
        getWindow().setAttributes(lp);     
        LinearLayout ll = new LinearLayout(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(500,500);
        params.setMargins(20, 0, 0, 0);
        ll.addView(new GradientView(this), params);    
        ll.addView(new GradientSurfaceView(this), params);
        ll.setOrientation(LinearLayout.VERTICAL);
        setContentView(ll);
    }


    public class GradientView extends View {

        public GradientView(Context context) {
            super(context);     
        }

        @Override
        protected void onDraw(Canvas canvas) {

            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(false);
            paint.setFilterBitmap(false);
            paint.setDither(false); 
            Shader shader = new LinearGradient(
                    0,
                    0,
                    0,
                    500,
                    //new int[]{0xffafafaf, 0xff414141},
                    new int[]{0xff333333, 0xff555555},
                    null,

                    Shader.TileMode.CLAMP
                    );

            paint.setShader(shader);    
            canvas.drawRect(0,0,500,500, paint);
        }       
    }




    public class GradientSurfaceView extends SurfaceView implements Callback {

        public GradientSurfaceView(Context context) {
            super(context);

            getHolder().setFormat(PixelFormat.RGBA_8888); // Ensure no banding on gradients 
            SurfaceHolder holder = getHolder();
            holder.addCallback(this);    
        }


        Paint paint;
        private GraphThread thread;

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            holder.setFormat(PixelFormat.RGBA_8888); // Ensure no banding on gradients    

            paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(false);
            paint.setFilterBitmap(false);
            paint.setDither(false); 

            Shader shader = new LinearGradient(
                    0,
                    0,
                    0,
                    500,
                    //new int[]{0xffafafaf, 0xff414141},
                    new int[]{0xff333333, 0xff555555},
                    null,
                    Shader.TileMode.CLAMP
                    );


            paint.setShader(shader);  



            thread = new GraphThread(holder, new Handler() );
            thread.setName("GradientSurfaceView_thread");
            thread.start();
        }

        class GraphThread extends Thread {

            /** Handle to the surface manager object we interact with */
            private SurfaceHolder mSurfaceHolder;   

            public GraphThread(SurfaceHolder holder, Handler handler) {
                mSurfaceHolder = holder;
                holder.setFormat(PixelFormat.RGBA_8888); // Ensure no banding on gradients  
            }

            @Override
            public void run() {

                Canvas c = null;

                while (true) {

                    try {
                        c = mSurfaceHolder.lockCanvas();

                        synchronized (mSurfaceHolder) {

                            if (c != null){


                                c.drawRect(0,0,500,500, paint);

                            }
                        }                                 
                    } 

                    finally {
                        if (c != null) {
                            mSurfaceHolder.unlockCanvasAndPost(c);
                        }
                    }
                }
            }    

        }

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

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
    }


}
Run Code Online (Sandbox Code Playgroud)

我已经从Google Play安装了一个名为Display Tester的应用程序.此应用程序可用于在屏幕上创建测试渐变.虽然它的渐变看起来并不完美,但它们看起来比我能够实现的要好一些,这让我想知道是否还有一项措施可以防止条带化.

我注意到的另一件事是Display Tester应用程序报告我的Nexus屏幕是32位.

有关信息,我明确启用硬件加速.我的SDK级别是:

 <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15"></uses-sdk>
Run Code Online (Sandbox Code Playgroud)

我注意到的另一件事是它的默认渐变背景Activity,我理解为Holo的一个特征,也是非常带状的.这也没有在屏幕截图中显示.而且,我也注意到我的Nexus 7上的背景条纹短暂移动,同时我的两个乐队运动也同情Views.如果我创建一个默认的"空"一个完全新的Android项目Activity,在Activity表演上我的Nexus和HTC都讨厌的带状渐变背景一个X.这是正常的吗?据我所知,这个黑/紫色渐变默认背景Activity是启用硬件加速时应具备的.好吧,无论硬件加速是否启用,我都会看到同样令人讨厌的带状Activity背景渐变.这甚至发生在我的空测试项目中,其目标SDK为15.为了澄清,我启用或禁用硬件加速的方式是明确使用android:hardwareAccelerated="true"android:hardwareAccelerated="false".

我不确定我对Holo黑色/紫色Activity渐变背景的观察是否与我的主要问题有关,但它看起来确实有点奇怪.奇怪的是它看起来质量很差(即带状),无论硬件加速是否打开,看起来都是一样的.因此,第二个问题是:如果你有一个Activity默认的Holo渐变背景,并且每个硬件加速的情况都是明确启用然后禁用,那么这个渐变背景(a)是否存在且(b)看起来非常平滑?我会在一个单独的问题中问这个,但同样,它似乎有关系.

所以,总结一下:我遇到的基本问题是SurfaceView在我的Nexus 7上应用渐变背景似乎无法完成.这不仅仅是条带问题(如果只是它,我可以乐意忍受)那); 事实上,每次抽奖时,条带本质上都是随机的.这意味着SurfaceView不断重绘的最终会产生移动的模糊背景.

Tre*_*vor 3

为了用一个答案来总结这个问题,我得出的结论是,Nexus 7 只是存在一些硬件/固件问题,这意味着它在渲染梯度方面完全失败了。