Android标题栏TitleBar全攻略
很多细心的网友发现Android浏览器的标题栏TitleBar的功能比较多,细心的网友在查看Browser时会发现,从左到右依次为网站图标(favicon)、标题、最右边的动画进度条(圆圈)、背景进度条(和前面的不在一层),今天我们就一起来看看Android标题栏高级实现方法。
在Android Browser程序中标题栏是自绘的,TitleBar类继承于线性布局LinearLayout类,通过LayoutInflater调用layout中的xml布局文件实现相关方法
public class TitleBar extends LinearLayout {
private TextView mTitle; //标题文字
private Drawable mCloseDrawable;
private ImageView mRtButton;
private Drawable mCircularProgress; //圆圈进度指示
private ProgressBar mHorizontalProgress; //水平进度条
private ImageView mFavicon; //网站图标
private ImageView mLockIcon;
private Drawable mStopDrawable; //停止状态的图标
private Drawable mBookmarkDrawable; //是一个书签的图标
private boolean mInLoad;
private BrowserActivity mBrowserActivity;
private Drawable mGenericFavicon; //如果站点没有favicon.ico时显示的默认图标
private int mIconDimension;
private View mTitleBg; //文字的背景
private MyHandler mHandler;
private static int LONG_PRESS = 1;
public TitleBar(BrowserActivity context) {
super(context, null);
mHandler = new MyHandler();
LayoutInflater factory = LayoutInflater.from(context);
factory.inflate(R.layout.title_bar, this); //从xml文件创建,android123提示大家,该文件的详细内容在本段代码最下方。
mBrowserActivity = context;
mTitle = (TextView) findViewById(R.id.title);
mTitle.setCompoundDrawablePadding(5);
mTitleBg = findViewById(R.id.title_bg);
mLockIcon = (ImageView) findViewById(R.id.lock);
mFavicon = (ImageView) findViewById(R.id.favicon);
mRtButton = (ImageView) findViewById(R.id.rt_btn);
Resources resources = context.getResources();
mCircularProgress = (Drawable) resources.getDrawable(com.android.internal.R.drawable.search_spinner);
mIconDimension = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20f,resources.getDisplayMetrics());
mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
mHorizontalProgress = (ProgressBar) findViewById(R.id.progress_horizontal);
mGenericFavicon = context.getResources().getDrawable(R.drawable.app_web_browser_sm);
}
private class MyHandler extends Handler {
public void handleMessage(Message msg) {
if (msg.what == LONG_PRESS) {
mTitleBg.setPressed(false);
mBrowserActivity.showTitleBarContextMenu();
}
}
};
@Override
protected void onCreateContextMenu(ContextMenu menu) { //创建上下文菜单,相关的xml代码在本文最后
MenuInflater inflater = mBrowserActivity.getMenuInflater();
inflater.inflate(R.menu.title_context, menu);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if ((int) event.getX() > mTitleBg.getRight()) {
mRtButton.setPressed(true);
} else {
mTitleBg.setPressed(true);
mHandler.sendMessageDelayed(mHandler.obtainMessage(
LONG_PRESS),
ViewConfiguration.getLongPressTimeout());
}
break;
case MotionEvent.ACTION_MOVE:
int slop = ViewConfiguration.get(mBrowserActivity)
.getScaledTouchSlop();
if ((int) event.getY() > getHeight() + slop) {
mTitleBg.setPressed(false);
mRtButton.setPressed(false);
mHandler.removeMessages(LONG_PRESS);
break;
}
int x = (int) event.getX();
int titleRight = mTitleBg.getRight();
if (mTitleBg.isPressed() && x > titleRight + slop) {
mTitleBg.setPressed(false);
mHandler.removeMessages(LONG_PRESS);
} else if (mRtButton.isPressed() && x < titleRight - slop) {
mRtButton.setPressed(false);
}
break;
case MotionEvent.ACTION_CANCEL:
mRtButton.setPressed(false);
mTitleBg.setPressed(false);
mHandler.removeMessages(LONG_PRESS);
break;
case MotionEvent.ACTION_UP:
if (mRtButton.isPressed()) {
if (mInLoad) {
mBrowserActivity.stopLoading();
} else {
mBrowserActivity.bookmarksOrHistoryPicker(false);
}
mRtButton.setPressed(false);
} else if (mTitleBg.isPressed()) {
mHandler.removeMessages(LONG_PRESS);
mBrowserActivity.onSearchRequested();
mTitleBg.setPressed(false);
}
break;
default:
break;
}
return true;
}
boolean isInLoad() {
return mInLoad;
}
void setFavicon(Bitmap icon) {
Drawable[] array = new Drawable[3];
array[0] = new PaintDrawable(Color.BLACK);
PaintDrawable p = new PaintDrawable(Color.WHITE);
array[1] = p;
if (icon == null) {
array[2] = mGenericFavicon;
} else {
array[2] = new BitmapDrawable(icon);
}
LayerDrawable d = new LayerDrawable(array);
d.setLayerInset(1, 1, 1, 1, 1);
d.setLayerInset(2, 2, 2, 2, 2);
mFavicon.setImageDrawable(d);
}
void setLock(Drawable d) {
if (null == d) {
mLockIcon.setVisibility(View.GONE);
} else {
mLockIcon.setImageDrawable(d);
mLockIcon.setVisibility(View.VISIBLE);
}
}
void setProgress(int newProgress) {
if (newProgress >= mHorizontalProgress.getMax()) {
mTitle.setCompoundDrawables(null, null, null, null);
((Animatable) mCircularProgress).stop();
mHorizontalProgress.setVisibility(View.INVISIBLE);
if (mBookmarkDrawable != null) {
mRtButton.setImageDrawable(mBookmarkDrawable);
}
mInLoad = false;
} else {
mHorizontalProgress.setProgress(newProgress);
if (!mInLoad && getWindowToken() != null) {
mTitle.setCompoundDrawables(null, null, mCircularProgress,
null);
((Animatable) mCircularProgress).start();
mHorizontalProgress.setVisibility(View.VISIBLE);
if (mBookmarkDrawable == null) {
mBookmarkDrawable = mRtButton.getDrawable();
}
if (mStopDrawable == null) {
mRtButton.setImageResource(R.drawable.ic_btn_stop_v2);
mStopDrawable = mRtButton.getDrawable();
} else {
mRtButton.setImageDrawable(mStopDrawable);
}
mInLoad = true;
}
}
}
void setTitleAndUrl(CharSequence title, CharSequence url) {
if (url == null) {
mTitle.setText(R.string.title_bar_loading);
} else {
mTitle.setText(url.toString());
}
}
void setToTabPicker() {
mTitle.setText(R.string.tab_picker_title);
setFavicon(null);
setLock(null);
mHorizontalProgress.setVisibility(View.GONE);
}
}
本文的相关的title_bar.xml布局文件内容,其中大家可以理解下部分图标在创建时使用隐藏GONE的visibility显示属性,通过条件来设置其显示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="8dip"
android:paddingRight="12dip"
android:paddingTop="2dip"
android:paddingBottom="1dip"
android:background="@drawable/search_plate_browser" >
<ProgressBar android:id="@+id/progress_horizontal"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="5dip"
android:max="100"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<LinearLayout android:id="@+id/title_bg"
android:background="@drawable/title_text"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<ImageView android:id="@+id/favicon"
android:layout_width="20dip"
android:layout_height="20dip"
android:layout_marginLeft="3dip"
/>
<ImageView android:id="@+id/lock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dip"
android:visibility="gone"
/>
<TextView
android:id="@+id/title"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1.0"
android:paddingLeft="8dip"
android:paddingRight="6dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/black"
android:gravity="center_vertical"
android:singleLine="true"
android:ellipsize="end"
/>
</LinearLayout>
<ImageView
android:id="@+id/rt_btn"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="6dip"
android:scaleType="center"
android:layout_marginBottom="4dip"
android:background="@drawable/btn_bookmark"
android:src="@drawable/ic_btn_bookmarks"
/>
</LinearLayout>
</LinearLayout>
以下为 title_context.xml,里面仅有两条一个为分享该页和复制本页的URL
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/title_bar_share_page_url"
android:title="@string/share_page"/>
<item android:id="@+id/title_bar_copy_page_url"
android:title="@string/copy_page_url"/>
</menu>
在Android Browser程序中标题栏是自绘的,TitleBar类继承于线性布局LinearLayout类,通过LayoutInflater调用layout中的xml布局文件实现相关方法
public class TitleBar extends LinearLayout {
private TextView mTitle; //标题文字
private Drawable mCloseDrawable;
private ImageView mRtButton;
private Drawable mCircularProgress; //圆圈进度指示
private ProgressBar mHorizontalProgress; //水平进度条
private ImageView mFavicon; //网站图标
private ImageView mLockIcon;
private Drawable mStopDrawable; //停止状态的图标
private Drawable mBookmarkDrawable; //是一个书签的图标
private boolean mInLoad;
private BrowserActivity mBrowserActivity;
private Drawable mGenericFavicon; //如果站点没有favicon.ico时显示的默认图标
private int mIconDimension;
private View mTitleBg; //文字的背景
private MyHandler mHandler;
private static int LONG_PRESS = 1;
public TitleBar(BrowserActivity context) {
super(context, null);
mHandler = new MyHandler();
LayoutInflater factory = LayoutInflater.from(context);
factory.inflate(R.layout.title_bar, this); //从xml文件创建,android123提示大家,该文件的详细内容在本段代码最下方。
mBrowserActivity = context;
mTitle = (TextView) findViewById(R.id.title);
mTitle.setCompoundDrawablePadding(5);
mTitleBg = findViewById(R.id.title_bg);
mLockIcon = (ImageView) findViewById(R.id.lock);
mFavicon = (ImageView) findViewById(R.id.favicon);
mRtButton = (ImageView) findViewById(R.id.rt_btn);
Resources resources = context.getResources();
mCircularProgress = (Drawable) resources.getDrawable(com.android.internal.R.drawable.search_spinner);
mIconDimension = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20f,resources.getDisplayMetrics());
mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
mHorizontalProgress = (ProgressBar) findViewById(R.id.progress_horizontal);
mGenericFavicon = context.getResources().getDrawable(R.drawable.app_web_browser_sm);
}
private class MyHandler extends Handler {
public void handleMessage(Message msg) {
if (msg.what == LONG_PRESS) {
mTitleBg.setPressed(false);
mBrowserActivity.showTitleBarContextMenu();
}
}
};
@Override
protected void onCreateContextMenu(ContextMenu menu) { //创建上下文菜单,相关的xml代码在本文最后
MenuInflater inflater = mBrowserActivity.getMenuInflater();
inflater.inflate(R.menu.title_context, menu);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if ((int) event.getX() > mTitleBg.getRight()) {
mRtButton.setPressed(true);
} else {
mTitleBg.setPressed(true);
mHandler.sendMessageDelayed(mHandler.obtainMessage(
LONG_PRESS),
ViewConfiguration.getLongPressTimeout());
}
break;
case MotionEvent.ACTION_MOVE:
int slop = ViewConfiguration.get(mBrowserActivity)
.getScaledTouchSlop();
if ((int) event.getY() > getHeight() + slop) {
mTitleBg.setPressed(false);
mRtButton.setPressed(false);
mHandler.removeMessages(LONG_PRESS);
break;
}
int x = (int) event.getX();
int titleRight = mTitleBg.getRight();
if (mTitleBg.isPressed() && x > titleRight + slop) {
mTitleBg.setPressed(false);
mHandler.removeMessages(LONG_PRESS);
} else if (mRtButton.isPressed() && x < titleRight - slop) {
mRtButton.setPressed(false);
}
break;
case MotionEvent.ACTION_CANCEL:
mRtButton.setPressed(false);
mTitleBg.setPressed(false);
mHandler.removeMessages(LONG_PRESS);
break;
case MotionEvent.ACTION_UP:
if (mRtButton.isPressed()) {
if (mInLoad) {
mBrowserActivity.stopLoading();
} else {
mBrowserActivity.bookmarksOrHistoryPicker(false);
}
mRtButton.setPressed(false);
} else if (mTitleBg.isPressed()) {
mHandler.removeMessages(LONG_PRESS);
mBrowserActivity.onSearchRequested();
mTitleBg.setPressed(false);
}
break;
default:
break;
}
return true;
}
boolean isInLoad() {
return mInLoad;
}
void setFavicon(Bitmap icon) {
Drawable[] array = new Drawable[3];
array[0] = new PaintDrawable(Color.BLACK);
PaintDrawable p = new PaintDrawable(Color.WHITE);
array[1] = p;
if (icon == null) {
array[2] = mGenericFavicon;
} else {
array[2] = new BitmapDrawable(icon);
}
LayerDrawable d = new LayerDrawable(array);
d.setLayerInset(1, 1, 1, 1, 1);
d.setLayerInset(2, 2, 2, 2, 2);
mFavicon.setImageDrawable(d);
}
void setLock(Drawable d) {
if (null == d) {
mLockIcon.setVisibility(View.GONE);
} else {
mLockIcon.setImageDrawable(d);
mLockIcon.setVisibility(View.VISIBLE);
}
}
void setProgress(int newProgress) {
if (newProgress >= mHorizontalProgress.getMax()) {
mTitle.setCompoundDrawables(null, null, null, null);
((Animatable) mCircularProgress).stop();
mHorizontalProgress.setVisibility(View.INVISIBLE);
if (mBookmarkDrawable != null) {
mRtButton.setImageDrawable(mBookmarkDrawable);
}
mInLoad = false;
} else {
mHorizontalProgress.setProgress(newProgress);
if (!mInLoad && getWindowToken() != null) {
mTitle.setCompoundDrawables(null, null, mCircularProgress,
null);
((Animatable) mCircularProgress).start();
mHorizontalProgress.setVisibility(View.VISIBLE);
if (mBookmarkDrawable == null) {
mBookmarkDrawable = mRtButton.getDrawable();
}
if (mStopDrawable == null) {
mRtButton.setImageResource(R.drawable.ic_btn_stop_v2);
mStopDrawable = mRtButton.getDrawable();
} else {
mRtButton.setImageDrawable(mStopDrawable);
}
mInLoad = true;
}
}
}
void setTitleAndUrl(CharSequence title, CharSequence url) {
if (url == null) {
mTitle.setText(R.string.title_bar_loading);
} else {
mTitle.setText(url.toString());
}
}
void setToTabPicker() {
mTitle.setText(R.string.tab_picker_title);
setFavicon(null);
setLock(null);
mHorizontalProgress.setVisibility(View.GONE);
}
}
本文的相关的title_bar.xml布局文件内容,其中大家可以理解下部分图标在创建时使用隐藏GONE的visibility显示属性,通过条件来设置其显示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="8dip"
android:paddingRight="12dip"
android:paddingTop="2dip"
android:paddingBottom="1dip"
android:background="@drawable/search_plate_browser" >
<ProgressBar android:id="@+id/progress_horizontal"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="5dip"
android:max="100"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<LinearLayout android:id="@+id/title_bg"
android:background="@drawable/title_text"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<ImageView android:id="@+id/favicon"
android:layout_width="20dip"
android:layout_height="20dip"
android:layout_marginLeft="3dip"
/>
<ImageView android:id="@+id/lock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dip"
android:visibility="gone"
/>
<TextView
android:id="@+id/title"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1.0"
android:paddingLeft="8dip"
android:paddingRight="6dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/black"
android:gravity="center_vertical"
android:singleLine="true"
android:ellipsize="end"
/>
</LinearLayout>
<ImageView
android:id="@+id/rt_btn"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="6dip"
android:scaleType="center"
android:layout_marginBottom="4dip"
android:background="@drawable/btn_bookmark"
android:src="@drawable/ic_btn_bookmarks"
/>
</LinearLayout>
</LinearLayout>
以下为 title_context.xml,里面仅有两条一个为分享该页和复制本页的URL
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/title_bar_share_page_url"
android:title="@string/share_page"/>
<item android:id="@+id/title_bar_copy_page_url"
android:title="@string/copy_page_url"/>
</menu>