【问题标题】:How add TextView in middle of SeekBar thumb? [duplicate]如何在 SeekBar 拇指中间添加 TextView? [复制]
【发布时间】:2014-02-21 18:09:43
【问题描述】:

我在 Android 中工作。我想做一个SeekBar。在SeekBar 的拇指中,我想显示进度(可能在与拇指一起移动的拇指上对齐的TextView 上)。

这是SeekBarTextViewXML

<SeekBar
    android:id="@+id/ProgressBar01"
    android:layout_width="fill_parent"
    android:paddingLeft="10px"
    android:paddingRight ="10px"
    android:layout_height="70dp"
    android:layout_below="@+id/incentives_textViewBottemLeft"
    android:max="10"
    android:progressDrawable="@drawable/incentive_progress"
    android:secondaryProgress="0"
    android:thumb="@drawable/incentives_progress_pin"
    android:focusable="false" />

<TextView
    android:id="@+id/incentives_textViewAbove_process_pin"
    android:layout_width="fill_parent"
    android:layout_height="20dp"
    android:layout_below="@+id/incentives_textViewBottemLeft"
    android:layout_marginTop="11dp"
    android:text=""
    android:textStyle="bold"
    android:textColor="#FFe4e1"
    android:textSize="15sp" />

这是我用来对齐文本的代码

int xPos = ((mSkbSample.getRight() - mSkbSample.getLeft()) / mSkbSample.getMax()) * mSkbSample.getProgress();
v1.setPadding(xPos+m,0,0,0);
v1.setText(String.valueOf(progress).toCharArray(), 0, String.valueOf(progress).length());  

但是文本没有显示在那个拇指的center中。请建议我该怎么做。

【问题讨论】:

标签: android android-layout view textview seekbar


【解决方案1】:

如果我正确理解您的问题,您希望将文本放在搜索栏上的拇指内,如下所示:

Android Seekbar 不公开任何允许您在拇指中设置文本的公共或受保护方法。因此,您无法按原样使用 Android SeekBar 实现解决方案。

作为一种解决方案,您可以编写自己的 CustomSeekBar。

Android SeekBar 扩展了 AbsSeekBar。在 AbsSeekBar 中设置拇指的位置,如下所示:

 private void setThumbPos(int w, Drawable thumb, float scale, int gap) {
    int available = w - mPaddingLeft - mPaddingRight;
    int thumbWidth = thumb.getIntrinsicWidth();
    int thumbHeight = thumb.getIntrinsicHeight();
    available -= thumbWidth;

    // The extra space for the thumb to move on the track
    available += mThumbOffset * 2;

    //Determine horizontal position
    int thumbPos = (int) (scale * available);

    //Determine vertical position
    int topBound, bottomBound;
    if (gap == Integer.MIN_VALUE) {
        Rect oldBounds = thumb.getBounds();
        topBound = oldBounds.top;
        bottomBound = oldBounds.bottom;
    } else {
        topBound = gap;
        bottomBound = gap + thumbHeight;
    }

    //Set the thumbs position
    thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);
}

在 AbsSeekBar 的 onDraw() 方法中,拇指被绘制:

mThumb.draw(canvas);

要实现您自己的 SeekBar,您首先创建一个扩展 AbsSeekBar 的 CustomSeekBar 类。然后,您在 CustomSeekBar 类中重写 AbsSeekBar 的 setThumPos() 方法,并在那里设置您自己的自定义拇指的位置。

您的自定义拇指将是一个视图或视图组,例如LinearLayout,带有背景可绘制对象和用于百分比进度文本的 TextView。

然后您必须决定如何将百分比进度写入自定义拇指。您可以在 setThumbPos() 内部调用的新 writeTextOnThumb 方法() 中将百分比进度文本写入拇指上,或者您可以将其公开为 CustomSeekBar 的 API 中的公共方法。

【讨论】:

  • 我在 seekbar thumb 上放置什么文本。我不明白你的意思,请将源代码发送到 saiyadamreddy@gmail.com。请帮助我提前谢谢。
  • @Gunnar Karlsson 你能用完整的解决方案更新你的答案吗?
  • 这个答案确实有其优点 - 但 setThumbPos() 是一种私有方法。您不能在 Java 中覆盖私有方法。
  • 我做不到......似乎更复杂:(
【解决方案2】:

在讨论解决方案的细节之前,我只提一些您可能已经考虑过的事情:用户在移动 SeekBar 时,通常将她的手指放在拇指上方,因此很可能会掩盖您的任何文本至少在移动 Seekbar 时可能会放在那里。现在,也许您正在以编程方式移动 SeekBar,或者您很高兴用户在完成移动并移开手指后查看 SeekBar,或者您可以指望用户滑动她的手指 在她开始滑动之后,SeekBar 下方,以便露出拇指。但如果情况并非如此,那么您可能希望将文本放置在用户手指可能所在的位置。

下面描述的方法应该允许您将文本放置在您喜欢的 SeekBar 中的任何位置,包括拇指上方。为此,它重写了 SeekBar 的基本 onDraw() 方法,而不是重写专门处理绘制拇指的方法。

这是一个使用上述方法将文本绘制到 SeekBar 上的类的粗略版本:

public class SeekBarWithText extends SeekBar {

  private static final int textMargin = 6;
  private static final int leftPlusRightTextMargins = textMargin + textMargin;
  private static final int maxFontSize = 18;
  private static final int minFontSize = 10;

  protected String overlayText;
  protected Paint textPaint;

  public SeekBarWithText(Context context) {
    super(context);
    Resources resources = getResources();

    //Set up drawn text attributes here
    textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    textPaint.setTypeface(Typeface.DEFAULT_BOLD);
    textPaint.setTextAlign(Align.LEFT);
  }

  //This attempts to ensure that the text fits inside your SeekBar on a resize
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    setFontSmallEnoughToFit(w - leftPlusRightTextMargins)));
  }

  //Finds the largest text size that will fit
  protected void setFontSmallEnoughToFit(int width) {
    int textSize = maxTextSize;
    textPaint.setTextSize(textSize);
    while((textPaint.measureText(sampleText) > width) && (textSize > minTextSize)) {
      textSize--;
      textPaint.setTextSize(textSize);
    }
  }

  //Clients use this to change the displayed text
  public void setOverlayText(String text) {
    this.overlayText = text;
    invalidate();
  }

  //Draws the text onto the SeekBar
  @Override
  protected synchronized void onDraw(Canvas canvas) {
    //Draw everything else (i.e., the usual SeekBar) first
    super.onDraw(canvas);

    //No text, no problem
    if(overlayText.length() == 0) {
      return;
    }

    canvas.save();

    //Here are a few parameters that could be useful in calculating where to put the text
    int width = this.getWidth() - leftPlusRightTextMargins;
    int height = this.getHeight();

    //A somewhat fat finger takes up about seven digits of space 
    // on each side of the thumb; YFMV
    int fatFingerThumbHangover = (int) textPaint.measureText("1234567");

    float textWidth = textPaint.measureText(overlayText);

    int progress = this.getProgress();
    int maxProgress = this.getMax();
    double percentProgress = (double) progress / (double) maxProgress;
    int textHeight = (int) (Math.abs(textPaint.ascent()) + textPaint.descent() + 1);

    int thumbOffset = this.getThumbOffset();

    //These are measured from the point textMargin in from the left of the SeekBarWithText view.
    int middleOfThumbControl = (int) ((double) width * percentProgress); 
    int spaceToLeftOfFatFinger = middleOfThumbControl - fatFingerThumbHangover;
    int spaceToRightOfFatFinger = (width - middleOfThumbControl) - fatFingerThumbHangover; 

    int spaceToLeftOfThumbControl = middleOfThumbControl - thumbOffset;
    int spaceToRightOfThumbControl = (width - middleOfThumbControl) - thumbOffset; 

    int bottomPadding = this.getPaddingBottom();
    int topPadding = this.getPaddingTop();

    //Here you will use the above and possibly other information to decide where you would 
    // like to draw the text.  One policy might be to draw it on the extreme right when the thumb
    // is left of center, and on the extreme left when the thumb is right of center.  These
    // methods will receive any parameters from the above calculations that you need to
    // implement your own policy.
    x = myMethodToSetXPosition();
    y = myMethodToSetYPosition();

    //Finally, just draw the text on top of the SeekBar
    canvas.drawText(overlayText, x, y, textPaint);

    canvas.restore();
  }
}

【讨论】:

  • 谢谢。一个问题:文本是否正好位于拇指中间这一行:int middleOfThumbControl = (int) ((double) width * percentProgress);。对于我的垂直搜索栏,它不是。因为 100%(percentProgress) 位于搜索栏的顶部,但拇指并没有将其中间移到顶部(只有拇指的顶部接触到搜索栏的顶部)你知道我的意思。我找不到适合所有屏幕尺寸的好解决方案,任何帮助都会很棒。
  • @Simon Schubert:我的代码用于水平的 SeekBar;我还没有尝试做垂直的。但是,您描述的问题似乎需要您偏移拇指高度的一半。 getThumbOffset() 可能会返回您需要的值。如果没有,您可以尝试 getThumb()(它返回一个 Drawable),然后检索该 Drawable 的高度以获得拇指的高度。
  • 谢谢卡尔。我完全(我相信)你说的做了,但这让我很害怕。坐标一直都有点错误。我最终覆盖了 setProgressAndThumb 方法并将文本绘制在可绘制对象的中间。感谢您的关注。
  • 我在我的应用程序中使用了这种方法的变体,它似乎工作得很好,所以也许你只需要调整它:play.google.com/store/apps/…
【解决方案3】:
check this put trees of relative layout to put text on top of seekbar

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/relativeLayout0" >

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/button1"
        android:layout_alignBottom="@+id/button1"
        android:layout_alignParentRight="true"
        android:text="Button" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button1"
        android:layout_marginBottom="0dp"
        android:layout_toRightOf="@+id/button1" >

        <SeekBar
            android:id="@+id/seekBar1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/seekBar1"
            android:layout_alignParentRight="true"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />

        <RelativeLayout
            android:id="@+id/relativeLayout1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true" >
        </RelativeLayout>

        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/relativeLayout1"
            android:layout_centerHorizontal="true"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    </RelativeLayout>
    enter code here
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"`enter code here`
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="24dp"
        android:text="Button" />

</RelativeLayout>

【讨论】:

  • 还请说明您的工作以及如何解决问题。只是粘贴一些代码可能会让一些读者感到困惑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多