編輯:關於Android編程
Tabbar最早出現在iOS,iOS中的TabBarController實現了這個功能,開發起來相當簡單。現在的APP,大多數都會使用Tabbar來作為應用的功能導航,界面簡單清晰。那麼Android常見的實現是通過RadioGroup來實現,今天將帶來自定義實現,補充RadioGroup實現的不足。
先看看常見的軟件中的使用:
這個是高鐵管家APP,大家應該非常熟悉。這個APP的首頁底部就是一個類似iOS的Tabbar。這裡就不多舉例子了,接下來直接進入正題。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxociAvPg0KPGgyIGlkPQ=="radiogroup實現tabbar">RadioGroup實現Tabbar
熟悉RadioGroup的都知道,一個RadioGroup中只能選中一個RadioButton。而Tabbar剛好就是這麼一個效果,所以用RadioGroup再好不過了。
- RadioGroup必須使用RadioButton作為子控件
- 由於Tabbar是上圖片、下文字,所有需要將android:button設置空,去掉RadioButton的默認圖。上圖片設置android:drawableTop屬性,文字設置android:text屬性,其他屬性按照實際需求調整即可。
- 實現起來很簡單,代碼頁比較簡潔。
TabGroup
這個類需要實現類似RadioGroup的作用,代碼借鑒RadioGroup實現。
package com.snicesoft.tabbar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
@SuppressLint(NewApi)
public class TabGroup extends LinearLayout {
public TabGroup(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public TabGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public TabGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TabGroup(Context context) {
super(context);
init();
}
private void init() {
setOrientation(HORIZONTAL);
}
int mCheckedId = -1;
OnTabGroupCheckedListener onTabGroupCheckedListener;
public void setOnTabGroupCheckedListener(
OnTabGroupCheckedListener onTabGroupCheckedListener) {
this.onTabGroupCheckedListener = onTabGroupCheckedListener;
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof TabItem) {
final TabItem tab = (TabItem) child;
if (tab.isChecked()) {
check(tab.getId());
}
}
super.addView(child, index, params);
}
public void check(int checkId) {
if (mCheckedId == checkId) {
return;
}
setCheckedStateForView(mCheckedId, false);
setCheckedId(checkId);
mCheckedId = checkId;
if (onTabGroupCheckedListener != null)
onTabGroupCheckedListener.onChecked(checkId);
}
private void setCheckedId(int id) {
View checkedView = findViewById(id);
if (checkedView != null && checkedView instanceof TabItem) {
((TabItem) checkedView).setChecked(true);
}
}
private void setCheckedStateForView(int viewId, boolean checked) {
View checkedView = findViewById(viewId);
if (checkedView != null && checkedView instanceof TabItem) {
((TabItem) checkedView).setChecked(checked);
}
}
public interface OnTabGroupCheckedListener {
public void onChecked(int checkedId);
}
}
TabItem
TabItem需要集成RadioButton的功能,也需要擴展性更強。所以選擇集成RelativeLayout,需要有check的狀態操作,那麼需要實現Checkable。
package com.snicesoft.tabbar;
import java.util.ArrayList;
import java.util.HashMap;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.RelativeLayout;
@SuppressLint(NewApi)
public class TabItem extends RelativeLayout implements Checkable {
private ArrayList chechableList = new ArrayList();
private HashMap stateListDrawableMap = new HashMap();
private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
public TabItem(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public TabItem(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public TabItem(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TabItem(Context context) {
super(context);
init();
}
private void init() {
super.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onChecked();
if (OnClickListener != null)
OnClickListener.onClick(v);
}
});
}
@Override
public void addView(View child, int index,
android.view.ViewGroup.LayoutParams params) {
super.addView(child, index, params);
setStates(child);
}
private void setStates(View child) {
Drawable drawable = child.getBackground();
if (drawable != null && drawable instanceof StateListDrawable) {
stateListDrawableMap.put(child, (StateListDrawable) drawable);
}
child.setClickable(false);
if (child instanceof Checkable) {
chechableList.add((Checkable) child);
}
if (child instanceof ViewGroup) {
final ViewGroup group = (ViewGroup) child;
if (group.getChildCount() > 0) {
for (int i = 0; i < group.getChildCount(); i++) {
setStates(group.getChildAt(i));
}
}
}
}
OnClickListener OnClickListener;
@Override
public void setOnClickListener(OnClickListener l) {
OnClickListener = l;
}
boolean isChecked = false;
@Override
public void setChecked(boolean checked) {
if (isChecked == checked)
return;
for (Checkable ca : chechableList) {
ca.setChecked(checked);
}
if (checked) {
for (View v : stateListDrawableMap.keySet()) {
StateListDrawable drawable = stateListDrawableMap.get(v);
drawable.setState(CHECKED_STATE_SET);
v.setBackground(drawable.getCurrent());
}
} else {
for (View v : stateListDrawableMap.keySet()) {
v.setBackground(stateListDrawableMap.get(v));
}
}
isChecked = checked;
}
private void onChecked() {
if (getParent() instanceof TabGroup) {
final TabGroup group = (TabGroup) getParent();
group.check(getId());
}
}
@Override
public boolean isChecked() {
return isChecked;
}
@Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
if (!pressed) {
setChecked(true);
}
}
@Override
public void toggle() {
setChecked(!isChecked);
}
}
RelativeLayout中的默認帶有Pressed屬性的組件,不如Button,會攔截onClick事件,所以TabItem中的所有組件都背設置不可點擊。
為了讓TabItem的兼容性達到RadioButton一樣,所以在setChecked方法中將TabItem中包含的所有集成Checkable的View強制調用setChecked方法,能夠達到同步效果(點擊TabItem的時候,能夠將check的狀態傳遞到子控件中) 為了讓TabItem中的組件能夠使用selector,需要用到StateListDrawable來控制不同狀態的背景顯示。
這種自定義控件,只是在原生控件的基礎上改進,是比較初級的,只需要掌握改進原理,修改的方法很多種的。本人的修改只是一個簡單的演示,希望大家有好的改進方法,不吝賜教。
QQ厘米秀是騰訊手機QQ新出的功能,玩家在手機QQ聊天中可以放上自己的厘米秀,也能發很多特定的帶有聲音的表情。QQ厘米秀讓用戶在手機QQ聊天中更有趣,而且目
先看看效果圖:package wuwang.tools.utils; import java.io.File; import java.io.FileInputStre
在學完了Android的基礎之後,我開始嘗試著寫一些小項目練練手,同時進一步鞏固自己的基礎知識,而我選的的第一個項目就是做一個簡單的人人對戰的五子棋小游戲。首先,我們要新
Visual Studio: C++跨平台的移動解決方案Visual Studio (下載地址) 正在迅速成為一個跨平台的C++IDE。我們的目標是讓Visual Stu