Вид обрезается выше ширины 10.000 пикселей - PullRequest
0 голосов
/ 07 января 2019

UPDATE: Работает на эмуляторе с Android Oreo (8.X). У меня есть возможность вносить изменения прямо в источники Android, так что было бы также полезно, если бы кто-то знал, что в источниках Android я должен изменить или обновить, чтобы это работало (поэтому мне не нужно обходной путь для Android 7 для этого . Обновление до Android 8, однако, невозможно.)

У меня SurfaceView внутри FrameLayout. SurfaceView обычно отображает видео, например, я рисую изображение. Проблема в том, что если я устанавливаю размер FrameLayout (или SurfaceView) выше 10.000 пикселей в ширину, он обрезается с левой стороны.

Протестировано на Android 7.1.1 (на устройстве и эмуляторе: Android TV (1080p) API 25

public class TestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //add surfaceview
        TestSurfaceView testSurfaceView = new TestSurfaceView(this);
        setContentView(testSurfaceView);

        //resize
        FrameLayout.LayoutParams bgParams = (FrameLayout.LayoutParams) testSurfaceView.getLayoutParams();

        //testcase full hd - working
        bgParams.width = 1920;

        //testcase 2 - working - each segment is 330px as 9900 / 1920 * 64 (default segment width) == 330
        //bgParams.width = 9900;

        //testcase 3 - working
        //bgParams.width = 10000;

        //testcase 4 - not working - each segment is 335px which is correct but first cell gets cropped by exactly 50px to the left
        //bgParams.width = 10050;

        bgParams.height = (int)Math.floor(bgParams.width * (9d/16d)); //16:9

        testSurfaceView.setX(0); //doesnt help

        /*
         Also the position counts into the 10000px limitation as you can see on following testcases
         */
        /*
        bgParams.width = 9900;
        bgParams.height = (int)Math.floor(bgParams.width * (9d/16d)); //16:9

        //works - as 9900 + 90 < 10000
        testSurfaceView.setX(90);

        //doesnt work, crops 50px to the left - 9900 + 150 -> 10050
        testSurfaceView.setX(150);
        */
    }
}

public class TestSurfaceView extends SurfaceView implements SurfaceHolder.Callback
{

public TestSurfaceView(TestActivity context) {
    super(context);

    SurfaceHolder holder = this.getHolder();
    holder.addCallback(this);
}

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder)
    {
        //load bitmap from file
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/testimg.png", options);

        Canvas c = surfaceHolder.lockCanvas();
        Rect rect = new Rect();
        rect.set(0,0, 1920, 1080); //image size

        Rect destRect = new Rect();
        destRect.set(0, 0, this.getWidth(), this.getHeight());

        //draw the image on the surface
        c.drawBitmap(bitmap, rect, destRect, null);
        surfaceHolder.unlockCanvasAndPost(c);
    }

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

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}
}

styles.xml - для темы

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen">
        <!-- Customize your theme here. -->
    </style>

</resources>

Приведенный выше код дает следующий вывод, который является правильным.

1920px Test Если я изменю bgParams.width на 9600 - он масштабируется правильно и по-прежнему отображается, начиная с левого края изображения:

9600px Test

Но если я изменю код, например 10050, изображение обрезается на 50 пикселей влево.

10050px test

Если я установлю:

destRect.set(50, 0, this.getWidth(), this.getHeight());

10050px test with pos 50px of image Он отображается правильно, но так как я не могу сделать это для MediaPlayer, и это супер странно, я пытаюсь найти хорошее решение.

Я также попытался установить размеры непосредственно в SurfaceView и вместо изменения параметров LayoutParams я попытался установить scaleX и scaleY для Framelayout, но в итоге получил те же результаты.

(кстати, максимальный размер текстуры opengl составляет около 16000 пикселей - установка его выше ~ 16000 пикселей приводит к черному экрану и исключению, так что это не является причиной проблемы)

Обновление: Размещены все источники. Во всяком случае, вот полный проект студии Android: Ссылка для скачивания проекта WeTransfer

...