Android SeekBars обрезается перед поворотом

Я пытаюсь создать вертикальный интерфейс в стиле микшера для управления различными источниками звука, используя Android SeekBars. Я могу вращать SeekBars, как описано во многих постах, и располагать их в правильном положении. Однако ширина каждого SeekBar (который мы видим как высота после его поворота) обрезается до доступной ширины родительского представления. В результате каждый SeekBar становится немного короче, потому что расстояние от его начальной позиции до правого края родительского элемента меньше. Они все должны быть на всю высоту этого изображения:

Вот код для его настройки; это у родителей setLayoutParams() поэтому SeekBars будет изменять размер всякий раз, когда изменяется родительский размер:

public void setLayoutParams (ViewGroup.LayoutParams params) {
    super.setLayoutParams(params);

    int sliderWidth = ViewUtils.scalePixels(this.app, 24);
    int sliderPadding = ViewUtils.scalePixels(this.app, 24);
    int iconSize = ViewUtils.scalePixels(this.app, 24);
    int iconPadding = ViewUtils.scalePixels(this.app, 8);
    int nextPosition = sliderPadding / ViewUtils.scalePixels(this.app, 2);

    // all the widths and heights are backwards here due to the rotation
    // rotating from the center created weirdness with the positioning
    this.masterSlider.setPivotX(0);
    this.recordingSlider.setPivotX(0);
    this.tempoSlider.setPivotX(0);
    this.pitchSlider.setPivotX(0);
    this.videoSlider.setPivotX(0);
    this.masterSlider.setPivotY(0);
    this.recordingSlider.setPivotY(0);
    this.tempoSlider.setPivotY(0);
    this.pitchSlider.setPivotY(0);
    this.videoSlider.setPivotY(0);
    this.masterSlider.setRotation(-90);
    this.recordingSlider.setRotation(-90);
    this.tempoSlider.setRotation(-90);
    this.pitchSlider.setRotation(-90);
    this.videoSlider.setRotation(-90);

    ViewUtils.setRelativeFrame(this.masterSlider, nextPosition, params.height - iconSize - iconPadding, params.height - iconSize - iconPadding, sliderWidth);
    ViewUtils.setRelativeFrame(this.masterIcon, nextPosition, params.height - iconSize, iconSize, iconSize);

    nextPosition += sliderWidth + sliderPadding;
    ViewUtils.setRelativeFrame(this.recordingSlider, nextPosition, params.height - iconSize - iconPadding, params.height - iconSize - iconPadding, sliderWidth);
    ViewUtils.setRelativeFrame(this.recordingIcon, nextPosition, params.height - iconSize, iconSize, iconSize);

    nextPosition += sliderWidth + sliderPadding;
    ViewUtils.setRelativeFrame(this.tempoSlider, nextPosition, params.height - iconSize - iconPadding, params.height - iconSize - iconPadding, sliderWidth);
    ViewUtils.setRelativeFrame(this.tempoIcon, nextPosition, params.height - iconSize, iconSize, iconSize);

    nextPosition += sliderWidth + sliderPadding;
    ViewUtils.setRelativeFrame(this.pitchSlider, nextPosition, params.height - iconSize - iconPadding, params.height - iconSize - iconPadding, sliderWidth);
    ViewUtils.setRelativeFrame(this.pitchIcon, nextPosition, params.height - iconSize, iconSize, iconSize);

    nextPosition += sliderWidth + sliderPadding;
    ViewUtils.setRelativeFrame(this.videoSlider, nextPosition, params.height - iconSize - iconPadding, params.height - iconSize - iconPadding, sliderWidth);
    ViewUtils.setRelativeFrame(this.videoIcon, nextPosition, params.height - iconSize, iconSize, iconSize);
}

setRelativeFrame это просто удобная функция для добавления RelativeLayoutParams:

public static void setRelativeFrame(View view, int x, int y, int w, int h) {
    RelativeLayout.LayoutParams layoutParams = null;
    if (view.getLayoutParams() instanceof RelativeLayout.LayoutParams) {
        layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams();
    }
    if (layoutParams == null) {
        layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    }
    layoutParams.leftMargin = x;
    layoutParams.topMargin = y;
    layoutParams.width = w;
    layoutParams.height = h;
    view.setLayoutParams(layoutParams);
}

Я получаю те же результаты на Android 8.1.0 и 5.1.1.

Родитель является RelativeLayout и имел setClipChildren(true) на этом, но я удалил это, и это не имело никакого значения.

Другой пост предложил добавить setLayerType(View.LAYER_TYPE_SOFTWARE, null) к SeekBars, но это не имело никакого значения.

Не имеет значения, поворачиваю ли я до или после установки размеров. Android по-прежнему ограничивает ширину доступным пространством, как будто SeekBar не поворачивается.

Я попытался создать новое представление, добавив SeekBar к представлению и повернув представление, но затем представление было обрезано так же, как и SeekBar. Таким образом, похоже, что это общая проблема с представлениями Android, а не только для SeekBars. Но я все еще не нашел решения с помощью более общих поисков.

Что ограничит размеры SeekBar их родительским представлением, и как я могу обойти это?

1 ответ

Я только что нашел обходной путь, который работает: я добавил внутреннее представление, ширина которого равна ширине родительского представления, а затем добавил к нему SeekBars. Внутреннее представление невидимо, поэтому вы не можете видеть, что оно шире родительского, но теперь SeekBars не обрезаются. Я оставлю это без ответа на случай, если будет более прямое решение.

Другие вопросы по тегам