Android UI customization-similar to the Tabbar of iOS
Android UI customization-similar to the Tabbar of iOS
Tabbar first appeared in iOS, and TabBarController in iOS implemented this function, which is quite simple to develop. Most of today's apps use Tabbar for functional navigation of applications, and the interface is simple and clear. The common implementation of Android is implemented through RadioGroup. Today, we will introduce custom implementation to supplement the shortcomings of RadioGroup implementation.
Let's take a look at the usage of common software:
This is the high-speed rail Butler APP, and everyone should be very familiar with it. At the bottom of the homepage of this APP is a Tabbar similar to iOS. There are not many examples here. Next we will go to the topic. <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4NCjxociAvPg0KPGgyIGlkPQ = "radiogroup implements tabbar"> RadioGroup implements Tabbar1. Why is RadioGroup used?
Anyone familiar with RadioGroup knows that only one RadioButton can be selected in a RadioGroup. Tabbar is just such an effect, so it is better to use RadioGroup.
2. Implementation Code
-RadioGroup must use RadioButton as the sub-control.
-Because Tabbar is a piece or bottom text, you need to leave android: button empty and remove the default RadioButton graph. Set the android: drawableTop attribute and the android: text attribute for text. adjust other attributes as needed.
-The implementation is simple and the code page is concise.
3. Advantages and Disadvantages: the code is concise and easy to implement. Disadvantages: lack of scalability. Because each Item is RadioButton, you can only use the functions of this space. If you need to expand it, you cannot do it. Custom Tabbar1. Requirement: for example, you need to add a message prompt similar to iOS badgeview to the message.
2. Implementation Code
TabGroup
This class needs to implement functions similar to RadioGroup, and the Code uses RadioGroup for implementation.
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 must be integrated with the RadioButton function and more scalable. Therefore, when you choose to integrate RelativeLayout, You need to perform check operations.
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); }}
By default, components with the Pressed attribute in RelativeLayout are not as good as buttons, and onClick events are blocked. Therefore, all components in TabItem are set to unclickable.
In order to make the TabItem compatibility the same as RadioButton, The setChecked method can be used to forcibly call the setChecked method for all views integrated with Checkable in TabItem to achieve the synchronization effect (when you click TabItem, can pass the check status to the sub-control) in order to allow the components in TabItem to use selector, StateListDrawable needs to be used to control the background display of different States. 3. Advantages and Disadvantages: The Use method is the same as RadioGroup, And the scalability is strong. Disadvantages: layout code is more than RadioGroup, and the default checked attribute is not set. Summary
This type of custom control is only improved on the basis of the native control. It is relatively Elementary. You only need to master the principle of improvement and there are many ways to modify it. My modifications are just a simple demonstration. I hope you will have a good way to improve it.