d.setState(getDrawableState());
d.setVisible(getVisibility() == VISIBLE, false); mButtonDrawable = d;
mButtonDrawable.setState(null);
setMinHeight(mButtonDrawable.getIntrinsicHeight()); } refreshDrawableState(); } @Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
boolean populated = super.dispatchPopulateAccessibilityEvent(event); if (!populated) {
int resourceId = 0; if (mChecked) {
resourceId = R.string.accessibility_compound_button_selected; } else {
resourceId = R.string.accessibility_compound_button_unselected; }
String state = getResources().getString(resourceId); event.getText().add(state); event.setChecked(mChecked); } return populated; } @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (verticalGravity) { case Gravity.BOTTOM: y = getHeight() - height; break;
case Gravity.CENTER_VERTICAL: y = (getHeight() - height) / 2;
break;
} buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height);
buttonDrawable.draw(canvas); }
} @Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET); }
return drawableState;
} @Override
protected void drawableStateChanged() { //android123提示状态改变时需要更换按钮的图标
super.drawableStateChanged(); if (mButtonDrawable != null) {
int[] myDrawableState = getDrawableState(); mButtonDrawable.setState(myDrawableState); invalidate(); }
} @Override
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || who == mButtonDrawable; } static class SavedState extends BaseSavedState {
boolean checked; SavedState(Parcelable superState) { super(superState); }
private SavedState(Parcel in) { super(in);
checked = (Boolean)in.readValue(null); } @Override
public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeValue(checked); } @Override
public String toString() {
return \
+ Integer.toHexString(System.identityHashCode(this)) + \
} public static final Parcelable.Creator
} public SavedState[] newArray(int size) { return new SavedState[size]; } };
} @Override
public Parcelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true);
Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Override
public void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout();
}
} 从上面来看我们知道CompuundButton的实现相对繁琐了些,主要是考虑状态是否已经选中等情况的消息通知,Android开发网提醒大家而ToggleButton相对CompuundButton增加的给用户而言主要是开关的文字显示。 public class ToggleButton extends CompoundButton {
private CharSequence mTextOn;
private CharSequence mTextOff;
private Drawable mIndicatorDrawable; private static final int NO_ALPHA = 0xFF; private float mDisabledAlpha;
public ToggleButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a =
context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.ToggleButton, defStyle, 0); mTextOn = a.getText(com.android.internal.R.styleable.ToggleButton_textOn); mTextOff = a.getText(com.android.internal.R.styleable.ToggleButton_textOff);
mDisabledAlpha
a.getFloat(com.android.internal.R.styleable.ToggleButton_disabledAlpha, 0.5f); syncTextState(); a.recycle();
} public ToggleButton(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.buttonStyleToggle); } public ToggleButton(Context context) { this(context, null); } @Override
public void setChecked(boolean checked) { super.setChecked(checked); syncTextState();
} private void syncTextState() { boolean checked = isChecked(); if (checked && mTextOn != null) { setText(mTextOn);
} else if (!checked && mTextOff != null) { setText(mTextOff); }
} public CharSequence getTextOn() { return mTextOn;
} public void setTextOn(CharSequence textOn) { mTextOn = textOn;
} public CharSequence getTextOff() {
=
return mTextOff;
} protected void onFinishInflate() { super.onFinishInflate();
updateReferenceToIndicatorDrawable(getBackground()); } @Override
public void setBackgroundDrawable(Drawable d) { super.setBackgroundDrawable(d);
updateReferenceToIndicatorDrawable(d);
} private void updateReferenceToIndicatorDrawable(Drawable backgroundDrawable) { if (backgroundDrawable instanceof LayerDrawable) {
LayerDrawable layerDrawable = (LayerDrawable) backgroundDrawable; mIndicatorDrawable =
layerDrawable.findDrawableByLayerId(com.android.internal.R.id.toggle); } }
@Override
protected void drawableStateChanged() { super.drawableStateChanged(); if (mIndicatorDrawable != null) {
mIndicatorDrawable.setAlpha(isEnabled() ? NO_ALPHA : (int) (NO_ALPHA * mDisabledAlpha));
} } }
49. AsyncTask实例代码演示Android异步任务
上次我们讲到了Android提供了一个较线程更简单的处理多任务的方法AsyncTask异步任务类,相对于线程来说AsyncTask对于简单的任务处理更安全,其内部的实现方法使用了Android的Handler机制,对于常见的文件下载可以使用AsyncTask类来处理,在Browser浏览器中就是用了该类下载Web服务器URL的Favicon图标。 首先Android123以简单的下载例子演示该类的大致结构,如下 private class DownloadFilesTask extends AsyncTask Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls); publishProgress((int) ((i / (float) count)100)); } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog(\ } } 最终我们执行 DownloadFilesTask().execute(url1, url2, url3); 即可。 在Android浏览器中下载Favicon图标的实现如下: class DownloadTouchIcon extends AsyncTask private final ContentResolver mContentResolver; private final Cursor mCursor; private final String mOriginalUrl; private final String mUrl; private final String mUserAgent; /* package */ BrowserActivity mActivity; public DownloadTouchIcon(BrowserActivity activity, ContentResolver cr, Cursor c, WebView view) { //构造方法 mActivity = activity; mContentResolver = cr; mCursor = c; mOriginalUrl = view.getOriginalUrl(); mUrl = view.getUrl(); mUserAgent = view.getSettings().getUserAgentString(); } public DownloadTouchIcon(ContentResolver cr, Cursor c, String url) { //实现本类的构造 mActivity = null; mContentResolver = cr; mCursor = c; mOriginalUrl = null; mUrl = url; mUserAgent = null; } @Override public Bitmap doInBackground(String... values) { //返回Bitmap类型 String url = values[0]; AndroidHttpClient client = AndroidHttpClient.newInstance(mUserAgent); HttpGet request = new HttpGet(url); HttpClientParams.setRedirecting(client.getParams(), true); //处理302等重定向问题 try { HttpResponse response = client.execute(request); (response.getStatusLine().getStatusCode() == 200) { //如果OK HttpEntity entity = response.getEntity(); if (entity != null) { InputStream content = entity.getContent(); //将图标保存到InputStream中,因为 if 是二进制内容 if (content != null) { Bitmap icon = BitmapFactory.decodeStream( //从流中取出Bitmap,这里使用了BitmapFactory类的静态方法decodeStream content, null, null);