Вид обрезается выше ширины 10.000 пикселей
ОБНОВЛЕНИЕ: Работает на эмуляторе с Android Oreo (8.X). Кто-то знает, где они могли что-то изменить в источниках Android, которые решили эту проблему?
У меня есть 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>
Код выше производит следующий вывод, который является правильным.
Если я изменю bgParams.width
до 9600 - корректно масштабируется и по-прежнему отображается, начиная с левого края изображения:
Но если я изменю код, например, на 10050, изображение обрезается на 50 пикселей влево.
Если я установлю:
destRect.set(50, 0, this.getWidth(), this.getHeight());
Он отображается правильно, но поскольку я не могу сделать это для MediaPlayer, и это супер странно, я пытаюсь найти хорошее решение.
Я также попытался установить размеры непосредственно в SurfaceView, и вместо изменения параметров LayoutParams я попытался установить scaleX и scaleY для Framelayout, но в итоге получил те же результаты.
(кстати, максимальный размер текстуры opengl составляет около 16000 пикселей - установка его выше ~16000 пикселей приводит к черному экрану и исключению, так что это не является причиной проблемы)
Обновление: размещены все источники. В любом случае, вот полный проект андроид-студии: [удалено - если кто-то снова захочет получить исходники, я могу их загрузить заново]