[Android开发]仿天天P图带气泡显示百分比进度的自定义SeekBar

仿天天P图图像美化修改工具,素材来自于天天P图,效果图

[Android开发]仿天天P图带气泡显示百分比进度的自定义SeekBar_第1张图片

效果就是点击之后会有气泡显示进度,优点是气泡不占用控件的高度

其他效果可参看https://github.com/AnderWeb/discreteSeekBar

实现方法:

添加OnSeekBarChangeListener,监听进度

	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);
		}
	};

在气泡类BubbleIndicator中,有个内部类Floater继承于framelayout用于显示数字气泡,气泡不通过重写seekbar的ondraw来绘制在seekbar中,而是通过WindowManager使用悬浮窗口的基本原理来添加view。

点击thumb,创建并且显示气泡

    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);
    }

气泡的初始x坐标是0,宽度屏幕宽,高度为thumb所在坐标减去气泡高度

    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;
    }
然后根据thumb中心位置调整气泡位置

    private void translateViewIntoPosition(final int x) {
        mPopupView.setFloatOffset(x + mDrawingLocation[0]);
    }
x是thumb所在rect的centerX,加上其坐在的初始位置,最终结果为移动后的位置。

然后在内部类floater中调整其位置

	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%");
            mMarker.setGravity(Gravity.CENTER);
            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+"%");
        }
    }

通过offsetLeftAndRight设置左右位移,位移距离为移动的距离减去移动前距离左边的距离

移动thumb时,同时移动气泡

	public void moveIndicator(Rect touchBounds, int progress) {
		if (!isShowing()) {
            return;
        }
		translateViewIntoPosition(touchBounds.centerX());
		mPopupView.setProgressText(progress);
	}
	
	private void translateViewIntoPosition(final int x) {
       	 	mPopupView.setFloatOffset(x + mDrawingLocation[0]);
    }
	
松开时,移除气泡、

	public void hideIndicator(){
		if (!isShowing()) {
            return;
        }
		mShowing = false;
		mWindowManager.removeView(mPopupView);
	}

代码地址:

http://download.csdn.net/detail/oshunz/9372241


你可能感兴趣的:(Android)