seekbar源码分析_Seekbar

hacker|
110

文章目录:

安卓开发!!!seekbar和textview结合,使textview 跟随thumb一起移动 怎么实现呢?textview 里显示数值

是不是要这个效果

主要思路是自定义一个SeekBar,然后上面的跟随窗口是用popwindow来实现的

主要的跟随代码如下:

protected synchronized void onDraw(Canvas canvas) {

// TODO Auto-generated method stub

int thumb_x = this.getProgress() * (this.getWidth() - mThumbWidth)

  / this.getMax();

int middle = this.getHeight() / 2+40;

  super.onDraw(canvas);

if (mPopupWindow != null) { 

 try {

  this.getLocationOnScreen(mPosition);

  mPopupWindow.update(thumb_x+mPosition[0] - getViewWidth(mView) / 2+mThumbWidth/2,

    middle,getViewWidth(mView),getViewHeight(mView));

 

 } catch (Exception e) {

  // TODO: handle exception

 }

  }

}

这段代码主要重写了seekbar的ondraw方法,来判断跟随窗口该显示在哪个地方

源码下载地址

Android手机怎么调耳机音量上限 源码

SeekBar mMusicVolume;

AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

int mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); //获取当前音乐音量

mMusicVolume.setMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)); //SEEKBAR设置为音量的最大阶数

mMusicVolume.setProgress(mVolume); //设置seekbar为当前音量进度

mMusicVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

@Override

public void onStopTrackingTouch(SeekBar seekBar) {

}

@Override

public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override

public void onProgressChanged(SeekBar seekBar, int progress,

boolean fromUser) {

mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0); //拖动seekbar时改变音量

}

});

android:如何将进度条(SeekBar),竖着布局?

读seekbar的源码,将方想反过来即可,在巴士上有现成的,你可以看看这个 ;tid=82748

运用子线程怎么编写seekbar

在 setProgress 的源码中,首先会判断当前线程是否为主UI线程,若是主UI线程则直接调用 doRefreshProgress 方法更新进度; 若不是主UI线程则会先创建一个RefreshProgressRunnable 对象,然后调用 view 的 post(Runnable action) 方法

从源码中浅析Android中怎么利用attrs和styles定义控件

1.attrs.xml:

我们知道Android的源码中有attrs.xml这个文件,这个文件实际上定义了所有的控件的属性,就是我们在布局文件中设置的各类属性

你可以找到attrs.xml这个文件,打开它,全选,右键-Show In-OutLine。可以看到整个文件的解构

我们大概可以看出里面是Android中的各种属性的声明,比如textStyle这个属性是这样定义的:

Java代码

!-- Default text typeface style. --

attr name="textStyle"

flag name="normal" value="0" /

flag name="bold" value="1" /

flag name="italic" value="2" /

/attr

那么现在你知道,我们在写android:textStyle的时候为什么会出现normal,bold和italic这3个东西了吧,就是定义在这个地方。

再看看textColor:

Java代码

!-- Color of text (usually same as colorForeground). --

attr name="textColor" format="reference|color" /

format的意思是说:这个textColor可以以两种方式设置,要么是关联一个值,要么是直接设置一个颜色的RGB值,这个不难理解,因为我们可以平时也这样做过。

也就是说我们平时在布局文件中所使用的各类控件的属性都定义在这里面,那么这个文件,除了定义这些属性外还定义了各种具体的组件,比如TextView,Button,SeekBar等所具有的各种特有的属性

比如SeekBar:

Java代码

declare-styleable name="SeekBar"

!-- Draws the thumb on a seekbar. --

attr name="thumb" format="reference" /

!-- An offset for the thumb that allows it to extend out of the range of the track. --

attr name="thumbOffset" format="dimension" /

/declare-styleable

也许你会问SeekBar的background,等属性怎么没有看到?这是因为Android中几乎所有的组件都是从View中继承下来的,SeekBar自然也不例外,而background这个属性几乎每个控件都有,因此被定义到了View中,你可以在declare-styleable:View中找到它。

总结下,也就是说attrs.xml这个文件定义了布局文件中的各种属性attr:***,以及每种控件特有的属性declare-styleable:***

2.styles.xml:

刚才的attrs.xml定义的是组件的属性,现在要说的style则是针对这些属性所设置的值,一些默认的值。

这个是SeekBar的样式,我们可以看到,这里面设置了一个SeekBar的默认的样式,即为attrs.xml文件中的各种属性设置初始值

Java代码

style name="Widget.SeekBar"

item name="android:indeterminateOnly"false/item

item name="android:progressDrawable"@android:drawable/progress_horizontal/item

item name="android:indeterminateDrawable"@android:drawable/progress_horizontal/item

item name="android:minHeight"20dip/item

item name="android:maxHeight"20dip/item

item name="android:thumb"@android:drawable/seek_thumb/item

item name="android:thumbOffset"8dip/item

item name="android:focusable"true/item

/style

这个是Button的样式:

Java代码

style name="Widget.Button"

item name="android:background"@android:drawable/btn_default/item

item name="android:focusable"true/item

item name="android:clickable"true/item

item name="android:textAppearance"?android:attr/textAppearanceSmallInverse/item

item name="android:textColor"@android:color/primary_text_light/item

item name="android:gravity"center_vertical|center_horizontal/item

/style

有了属性和值,但是这些东西是如何关联到一起的呢?它们如何被android的framework层所识别呢?

3.组件的源码

我们看下TextView的源码:

Java代码

public TextView(Context context) {

this(context, null);

}//这个构造器用来给用户调用,比如new TextView(this);

public TextView(Context context,

AttributeSet attrs) {

this(context, attrs, com.android.internal.R.attr.textViewStyle);

}

public TextView(Context context,

AttributeSet attrs,

int defStyle) {

super(context, attrs, defStyle);//为用户自定义的TextView设置默认的style

mText = "";

//设置画笔

mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);

mTextPaint.density = getResources().getDisplayMetrics().density;

mTextPaint.setCompatibilityScaling(

getResources().getCompatibilityInfo().applicationScale);

mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

mHighlightPaint.setCompatibilityScaling(

getResources().getCompatibilityInfo().applicationScale);

mMovement = getDefaultMovementMethod();

mTransformation = null;

//attrs中包含了这个TextView控件在布局文件中定义的属性,比如android:background,android:layout_width等

//com.android.internal.R.styleable.TextView中包含了TextView中的针对attrs中的属性的默认的值

//也就是说这个地方能够将布局文件中设置的属性获取出来,保存到一个TypeArray中,为这个控件初始化各个属性

TypedArray a =

context.obtainStyledAttributes(

attrs, com.android.internal.R.styleable.TextView, defStyle, 0);

int textColorHighlight = 0;

ColorStateList textColor = null;

ColorStateList textColorHint = null;

ColorStateList textColorLink = null;

int textSize = 15;

int typefaceIndex = -1;

int styleIndex = -1;

/*

* Look the appearance up without checking first if it exists because

* almost every TextView has one and it greatly simplifies the logic

* to be able to parse the appearance first and then let specific tags

* for this View override it.

*/

TypedArray appearance = null;

//TextView_textAppearance不太了解为什么要这样做?难道是为了设置TextView的一些默认的属性?

int ap = a.getResourceId(com.android.internal.R.styleable.TextView_textAppearance, -1);

if (ap != -1) {

appearance = context.obtainStyledAttributes(ap,

com.android.internal.R.styleable.

TextAppearance);

}

if (appearance != null) {

int n = appearance.getIndexCount();

for (int i = 0; i n; i++) {

int attr = appearance.getIndex(i);

switch (attr) {

case com.android.internal.R.styleable.TextAppearance_textColorHighlight:

textColorHighlight = appearance.getColor(attr, textColorHighlight);

break;

case com.android.internal.R.styleable.TextAppearance_textColor:

textColor = appearance.getColorStateList(attr);

break;

case com.android.internal.R.styleable.TextAppearance_textColorHint:

textColorHint = appearance.getColorStateList(attr);

break;

case com.android.internal.R.styleable.TextAppearance_textColorLink:

textColorLink = appearance.getColorStateList(attr);

break;

case com.android.internal.R.styleable.TextAppearance_textSize:

textSize = appearance.getDimensionPixelSize(attr, textSize);

break;

case com.android.internal.R.styleable.TextAppearance_typeface:

typefaceIndex = appearance.getInt(attr, -1);

break;

case com.android.internal.R.styleable.TextAppearance_textStyle:

styleIndex = appearance.getInt(attr, -1);

break;

}

}

appearance.recycle();

}

//各类属性

boolean editable = getDefaultEditable();

CharSequence inputMethod = null;

int numeric = 0;

CharSequence digits = null;

boolean phone = false;

boolean autotext = false;

int autocap = -1;

int buffertype = 0;

boolean selectallonfocus = false;

Drawable drawableLeft = null, drawableTop = null, drawableRight = null,

drawableBottom = null;

int drawablePadding = 0;

int ellipsize = -1;

boolean singleLine = false;

int maxlength = -1;

CharSequence text = "";

CharSequence hint = null;

int shadowcolor = 0;

float dx = 0, dy = 0, r = 0;

boolean password = false;

int inputType = EditorInfo.TYPE_NULL;

int n = a.getIndexCount();

for (int i = 0; i n; i++) {

int attr = a.getIndex(i);

//通过switch语句将用户设置的,以及默认的属性读取出来并初始化

switch (attr) {

case com.android.internal.R.styleable.TextView_editable:

editable = a.getBoolean(attr, editable);

break;

case com.android.internal.R.styleable.TextView_inputMethod:

inputMethod = a.getText(attr);

break;

case com.android.internal.R.styleable.TextView_numeric:

numeric = a.getInt(attr, numeric);

break;

//更多的case语句...

case com.android.internal.R.styleable.TextView_textSize:

textSize = a.getDimensionPixelSize(attr, textSize);//设置当前用户所设置的字体大小

break;

case com.android.internal.R.styleable.TextView_typeface:

typefaceIndex = a.getInt(attr, typefaceIndex);

break;

//更多的case语句...

}

通过上面的代码大概可以知道,每个组件基本都有3个构造器,其中只传递一个Context上下文的那个构造器一般用来在java代码中实例化使用。

比如你可以

Java代码

TextView tv = new TextView(context);

来实例化一个组件。

最终调用的是第3个构造器

Java代码

public TextView(Context context,

AttributeSet attrs,

int defStyle)

在这个构造器中为你设置了默认的属性attrs和值styles。关键不在这里,而是后面通过使用下面的代码

Java代码

TypedArray a =

context.obtainStyledAttributes(

attrs, com.android.internal.R.styleable.TextView, defStyle, 0);

来将属性和值获取出来,放到一个TypeArray中,然后再利用一个switch语句将里面的值取出来。再利用这些值来初始化各个属性。这个View最终利用这些属性将这个控件绘制出来。

如果你在布局文件中定义的一个View的话,那么你定义的值,会被传递给构造器中的attrs和styles。也是利用同样的方式来获取出你定义的值,并根据你定义的值来绘制你想要的控件。

再比如其实Button和EditText都是继承自TextView。看上去两个控件似乎差异很大,其实不然。Button的源码其实相比TextView变化的只是style而已:

2条大神的评论

  • avatar
    访客 2022-07-10 上午 10:55:40

    @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgre

  • avatar
    访客 2022-07-10 上午 02:33:04

    com.android.internal.R.styleable. TextAppearance); } if (appearance != null) {

发表评论