我们经常会用到带气泡问题提示的拖动seekbar。这里有一个非常好用的自定义seekbar框架BubbleSeekBar开源框架:https://github.com/widegalaxy/BubbleSeekBar/tree/5ccf3e91f0cc7e8ac5c338ae8ca709c2324bef59
但我在项目中使用的时候发现了一个问题,在android7.0系统上,竟然不能适配。想了很多解决办法,最后无解。如果哪位大神有好的解决方法,希望不吝赐教。查了很多资料只查到了PopupWindow 在 Android N(7.0) 的兼容性问题(解决方法:http://www.jianshu.com/p/0df10893bf5b)。但BubbleSeekBar的问题还是没有解决。它存在问题的主要代码是这块:
if (mLayoutParams == null) {
mLayoutParams = new WindowManager.LayoutParams();
mLayoutParams.gravity = Gravity.TOP | GravityCompat.START;
mLayoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
mLayoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
mLayoutParams.format = PixelFormat.TRANSLUCENT;
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mLayoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;//展示类型Toast
mLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
}
mLayoutParams.x = (int) mBubbleCenterRawX;
mLayoutParams.y = (int) mBubbleCenterRawSolidY;
mBubbleView.setAlpha(0);
mBubbleView.setVisibility(VISIBLE);
mBubbleView.animate().alpha(1f).setDuration(200)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
try {
mWindowManager.addView(mBubbleView, mLayoutParams);
} catch (Exception x) {
}
}
}).start();
后来没办法,只能重新找了一个自定义控件,修改成了自己想要的样式。
新的自定义控件有两个类组成,代码如下:
public class BubbleIndicator {
private final WindowManager mWindowManager;
private boolean mShowing;
private int[] mDrawingLocation = new int[2];
Point screenSize = new Point();
private Floater mPopupView;
public BubbleIndicator(Context context, AttributeSet attrs, int defStyleAttr, String maxValue) {
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mPopupView = new Floater(context, attrs, defStyleAttr, maxValue);
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
screenSize.set(displayMetrics.widthPixels, displayMetrics.heightPixels);
}
public void showIndicator(View parent, Rect touchBounds) {
if (isShowing()) {
return;
}
IBinder windowToken = parent.getWindowToken();
if (windowToken != null) {
WindowManager.LayoutParams p = createPopupLayout(windowToken);
p.gravity = Gravity.TOP | GravityCompat.START;
updateLayoutParamsForPosiion(parent, p);
mShowing = true;
translateViewIntoPosition(touchBounds.centerX());
invokePopup(p);
}
}
private WindowManager.LayoutParams createPopupLayout(IBinder windowToken) {
WindowManager.LayoutParams p = new WindowManager.LayoutParams();
p.gravity = Gravity.START | Gravity.TOP;
p.width = ViewGroup.LayoutParams.MATCH_PARENT;
p.height = ViewGroup.LayoutParams.MATCH_PARENT;
p.format = PixelFormat.TRANSLUCENT;
p.flags = computeFlags(p.flags);
p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
p.token = windowToken;
p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
return p;
}
private void invokePopup(WindowManager.LayoutParams p) {
mWindowManager.addView(mPopupView, p);
}
public void moveIndicator(Rect touchBounds, int progress) {
if (!isShowing()) {
return;
}
translateViewIntoPosition(touchBounds.centerX());
mPopupView.setProgressText(progress);
}
public void hideIndicator() {
if (!isShowing()) {
return;
}
mShowing = false;
mWindowManager.removeView(mPopupView);
}
private void translateViewIntoPosition(final int x) {
mPopupView.setFloatOffset(x + mDrawingLocation[0]);
}
private void updateLayoutParamsForPosiion(View anchor, WindowManager.LayoutParams p) {
measureFloater();
int measuredHeight = mPopupView.getMeasuredHeight();
anchor.getLocationInWindow(mDrawingLocation);
p.x = 0;
p.y = mDrawingLocation[1] - measuredHeight;
p.width = screenSize.x;
p.height = measuredHeight;
}
private void measureFloater() {
int specWidth = View.MeasureSpec.makeMeasureSpec(screenSize.x, View.MeasureSpec.EXACTLY);
int specHeight = View.MeasureSpec.makeMeasureSpec(screenSize.y, View.MeasureSpec.AT_MOST);
mPopupView.measure(specWidth, specHeight);
}
private boolean isShowing() {
return mShowing;
}
private int computeFlags(int curFlags) {
curFlags &= ~(
WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
return curFlags;
}
private class Floater extends FrameLayout {
public TextView mMarker;
private int mOffset;
public Floater(Context context, AttributeSet attrs, int defStyleAttr, String maxValue) {
super(context);
mMarker = new TextView(context);
mMarker.setText("0.0");
// mMarker.setGravity(Gravity.CENTER);
mMarker.setPadding(20, 5, 5, 10);
mMarker.setTextColor(getResources().getColor(R.color.white));
mMarker.setBackgroundResource(R.drawable.tooltip_bg);
addView(mMarker, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSie = mMarker.getMeasuredHeight();
setMeasuredDimension(widthSize, heightSie);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int centerDiffX = (mMarker.getMeasuredWidth() - mMarker.getPaddingLeft()) / 2;
int offset = mOffset - centerDiffX;
mMarker.layout(offset, 0, offset + mMarker.getMeasuredWidth(), mMarker.getMeasuredHeight());
}
public void setFloatOffset(int x) {
mOffset = x;
int centerDiffX = (mMarker.getMeasuredWidth() - mMarker.getPaddingLeft()) / 2;
int offset = mOffset - centerDiffX;
mMarker.offsetLeftAndRight(offset - mMarker.getLeft());
}
public void setProgressText(int progress) {
mMarker.setText("" + progress + "%");
}
}
}
public class BubbleSeekBar extends android.support.v7.widget.AppCompatSeekBar {
private Drawable mThumbDrawable;
private BubbleIndicator mBubbleIndicator;
public BubbleSeekBar(Context context) {
this(context, null);
}
public BubbleSeekBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BubbleSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mBubbleIndicator = new BubbleIndicator(context, attrs, defStyleAttr, "100");
setOnSeekBarChangeListener(mOnSeekBarChangeListener);
}
@Override
public void setThumb(Drawable thumb) {
super.setThumb(thumb);
mThumbDrawable = thumb;
}
private OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//mBubbleIndicator.hideIndicator();//手松开后,隐藏气泡问题提示
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mBubbleIndicator.showIndicator(seekBar, mThumbDrawable.getBounds());
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser)
mBubbleIndicator.moveIndicator(mThumbDrawable.getBounds(), progress);
}
};
}
用的时候,直接在布局文件中添加自定义控件即可
<?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"
tools:context="com.beibaokongming.seekbardemo.Main2Activity">
<com.beibaokongming.seekbardemo.BubbleSeekBar
style="@style/SeekBar"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="196dp" />
</RelativeLayout>
源码下载地址:http://download.csdn.net/detail/beibaokongming/9823949