Android 6.0 Marshmallow停止显示垂直SeekBar拇指

7
我一直在使用这个基本的包装器来包装SeekBar,但发现它会隐藏拇指,或者在Marshmallow下做一些奇怪的事情,比如让它在白色背景下变成白色。
我使用AS的“BlankActivity”向导创建了一个项目来说明这一点,在默认设置下除了描述的内容之外没有更改任何内容。左边是Lollipop,在Marshmallow下运行相同的代码:

enter image description here

有一个自定义的水平SeekBar用于测试是否存在问题,但并没有。左侧的第一个垂直SeekBar没有样式,在Marshmallow之前是可以的,但在之后就不行了;中间的SeekBar明确使用Widget.Material.Light.SeekBar样式以测试默认值是否被正确选择;最后一个SeekBar给出了一个重要提示,因为它使用旧的Widget.Holo.SeekBar样式,看起来像几年前的。

这是布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    >

    <com.otamate.seekbarmarshbug.CustomSeekBar
        android:id="@+id/seekBarCustom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <com.otamate.seekbarmarshbug.VerticalSeekBar
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_below="@+id/seekBarCustom"
        />

    <com.otamate.seekbarmarshbug.VerticalSeekBar
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:layout_below="@+id/seekBarCustom"
        android:layout_centerHorizontal="true"
        style="@android:style/Widget.Material.Light.SeekBar"
        />

    <com.otamate.seekbarmarshbug.VerticalSeekBar
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/seekBarCustom"
        style="@android:style/Widget.Holo.SeekBar"
        />

</RelativeLayout>

自定义SeekBar:

package com.otamate.seekbarmarshbug;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.SeekBar;

public class CustomSeekBar extends SeekBar {

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

    public CustomSeekBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

和VerticalSeekBar:

package com.otamate.seekbarmarshbug;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;

public class VerticalSeekBar extends SeekBar {

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

    public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public VerticalSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    protected void onDraw(Canvas c) {
        c.rotate(-90);
        c.translate(-getHeight(), 0);

        super.onDraw(c);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;

            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return true;
    }

}

这个 bug 在 com.android.support:appcompat-v7:23.1.0 中 几乎 已经修复。使用这个版本,拇指看起来与这里展示的代码中的水平拇指相同,除了在被选中和移动时没有动画效果(闪烁出现在其边界上的响应“鼓起和扩张”的波纹效果),你只会看到一圈无聊但是功能正常的圆形。 - Carl Whalley
1
在这里使用appcompat-v7:23.1.1。在Marshmallow上,拇指完全不可见。最终创建了一个自定义的拇指,它可以正常工作。 - Matthias
4个回答

7

试试这段代码,它能很好地运行!

<seekBar>
   .....
   android:splitTrack="false"
</seekBar>

它对我在Android 7.0 Nougat上很有帮助 :) - elementstyle
救了我的一天!谢谢。 - Androbean Studio
我不知道你是怎么想出来的,但是没错,它可以运行...谢谢! - hlascelles

7

看起来棉花糖操作系统在画布上出了点问题。我实施了一个简单的修复方法。

我在自定义垂直SeekBar的两个方法中进行了修改。

protected void onDraw(Canvas c) {
    c.rotate(-90);
    c.translate(-getHeight(), 0);
    drawThumb(c); //redrawing thumb

    super.onDraw(c);
}

void drawThumb(Canvas canvas) {
    Drawable thumb = getThumb();
    if (thumb != null) {
        Rect thumbBounds = thumb.getBounds();
        canvas.save();
        canvas.rotate(90, thumbBounds.exactCenterX(), thumbBounds.exactCenterY());
        thumb.draw(canvas);
        canvas.restore();
    }
}

编辑:此方法仅适用于Marshmallow设备。如果您尝试在早期版本的设备上使用此方法,它们将显示两个拇指。如果您想要在所有设备上使用此方法,则需要通过使用自定义属性来完全重新绘制拇指。

请查看此 GitHub 仓库中可与 M 兼容的 VerticalSeekBar https://github.com/3drobotics/AndroidWidgets


1
运行良好,只需使用:if(android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.M)drawThumb(c);除了会导致拇指朝下之外,这将像魔术一样工作。我通过在drawables-v24文件夹中添加一个新版本的我的thumb来解决这个问题:<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <rotate android:drawable="@drawable/ic_search" android:fromDegrees="180" /> </item> </layer-list> - Santi Iglesias

1
我也在使用垂直SeekBar,并遇到了同样的问题。 这个方法对我有用:
在onCreate中:
    ViewTreeObserver vto = mSeekBar.getViewTreeObserver();
    vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            Resources res = getResources();
            Drawable thumb_image = res.getDrawable(R.drawable.vertseekbarthumb);
            int h = (int) (mSeekBar.getMeasuredWidth());
            int w = (int) (h);
            Bitmap bmpOrg = ((BitmapDrawable) thumb_image).getBitmap();
            Bitmap bmpScaled = Bitmap.createScaledBitmap(bmpOrg, w, h, true);
            mNewThumb = new BitmapDrawable(res, bmpScaled);
            mNewThumb.setBounds(0, 0, mNewThumb.getIntrinsicWidth(), mNewThumb.getIntrinsicHeight());
            mSeekBar.setThumb(mNewThumb);
            mSeekBar.getViewTreeObserver().removeOnPreDrawListener(this);
            mSeekBar.setProgressAndThumb(45);
            return true;
        }
    });

在 Android 6.0 之前,我已经有了 onPreDraw 调用,在它停止显示拇指后,我实际上只添加了这个调用:

mSeekBar.setProgressAndThumb(45);

而且它也可以在棉花糖上运行。45只是我想把拇指设置为的进度,因为我的SeekBar的最大进度为90,我希望它在中间。所以你必须根据你的进度更改这个数字。


这就是我一直在寻找的! - Hossam Alaa

-1

只需使用普通的SeekBar,并使用android:rotation="270",这对我很有帮助。

<SeekBar
android:id="@+id/seekBar"
android:rotation="270"
/>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接