如何改变windows表面的大小?

时间:2014-08-08 23:39:35

标签: java android android-activity surfaceview android-windowmanager

所以我知道可以通过调用SurfaceHolder上的setFixedSize()来更改SurfaceView的表面大小,但是当我尝试在任意窗口上执行相同的操作时,从一个活动中获取,我不能。这是相关的测试代码:

public class TestActivity extends Activity implements Callback2 {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getWindow().takeSurface(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        arg0.setFixedSize(300, 300);
    }
}

这会导致以下错误日志:

  

01-15 23:21:46.111:E / AndroidRuntime(9748):致命异乎寻常:主

     

01-15 23:21:46.111:E / AndroidRuntime(9748):进程:com.example.windowtest,PID:9748

     

01-15 23:21:46.111:E / AndroidRuntime(9748):java.lang.UnsupportedOperationException:目前仅支持从布局调整大小

     

01-15 23:21:46.111:E / AndroidRuntime(9748):在android.view.ViewRootImpl $ TakenSurfaceHolder.setFixedSize(ViewRootImpl.java:6094)

在布局中,我认为它意味着WindowManager.LayoutParams,它也会调整Window的尺寸。那么在不改变Window的尺寸的情况下,是否无法改变Window Surface的大小?我认为有,因为我们可以使用SurfaceView,但我不确定如何。

先谢谢!

编辑:此外,SurfaceView setFixedSize()调用会生成requestLayout(),它会传播到实现ViewParent接口的对象。什么是在运行时附加到SurfaceView的ViewParent对象?也许那么表面缓冲区如何调整大小背后的逻辑将是明确的。

2 个答案:

答案 0 :(得分:1)

实际上可以使用NDK的ANativeWindow_setBuffersGeometry

JNIEXPORT void JNICALL Java_com_organization_app_TestActivity_setBufferGeometry(JNIEnv *env, jobject thiz, jobject surface, jint width, jint height)
{
    __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "setBufferGeometry(): %p %dx%d", surface, width, height);
    ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
    __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "setBufferGeometry(): window: %p", window);
    ANativeWindow_setBuffersGeometry(window, width, height, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM);
}

Java代码:

private static native void setBufferGeometry(Surface surface, int width , int height );

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
    Log.d( TAG, "surfaceChanged()...");
    setBufferGeometry(holder.getSurface(), 768, 1366);
    /* ... */

来自ANativeWindow_setBuffersGeometry文档:

  

更改窗口缓冲区的格式和大小。

     

宽度和高度控制缓冲区中的像素数,而不是   屏幕上窗口的尺寸。 如果这些与   窗口的物理尺寸,则其缓冲区将被缩放以匹配   将其合成到屏幕上时的大小。

答案 1 :(得分:0)

所有基于视图的UI都在单个图层上(a / k / a窗口)。您无法更改单个视图的曲面缩放比例;这没有意义。您必须更改整个View合成曲面的设置,框架并不想让您这样做。

SurfaceView的表面位于一个单独的图层上,独立合成,因此您可以更自由地更改其尺寸。

另请参阅:Android System-Level Graphics