- 浏览: 132268 次
- 性别:
- 来自: 鄂州
最新评论
-
xingfuyizhan:
写的很好,谢谢分享
方便实用的下拉刷新控件,支持ScrollView、AbsListView -
xingfuyizhan:
在Fragment中使用布局怎么显示不出来
方便实用的下拉刷新控件,支持ScrollView、AbsListView -
飞不过海:
Mybeautiful 写道显然有问题,return Bitm ...
Android根据指定的尺寸加载Bitmap -
Mybeautiful:
显然有问题,return BitmapFactory.deco ...
Android根据指定的尺寸加载Bitmap -
xhAndroid:
加入我工程的时候有个诡异的bug,下拉刷新布局就会覆盖主Vie ...
方便实用的下拉刷新控件,支持ScrollView、AbsListView
需求:
Android自带的TabHost为橫向的,而且样式已经写死了,不能改变。
而我需要做一个纵向(垂直)的TabHost界面,达到如下效果:
使劲想套用API的TabHost,但是它里面的TabWidget的方向写死的,请看:
private void initTabWidget() { setOrientation(LinearLayout.HORIZONTAL);
只好自已重写一个TabHost布局,代码如下:
package com.xwangly.tabhost; import java.util.ArrayList; import java.util.List; import android.app.LocalActivityManager; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; import android.view.View.OnKeyListener; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; //import android.widget.TabHost; //import android.widget.TabWidget; import android.widget.TextView; import android.widget.TabHost.OnTabChangeListener; /*import android.widget.TabHost.OnTabChangeListener; import android.widget.TabHost.TabContentFactory;*/ //import android.widget.TabHost.TabSpec; public class MyTabHostLayout extends FrameLayout implements ViewTreeObserver.OnTouchModeChangeListener{ private LinearLayout mTabWidget; private FrameLayout mTabContent; private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2); protected int mCurrentTab = -1; private View mCurrentView = null; protected LocalActivityManager mLocalActivityManager = null; private OnTabChangeListener mOnTabChangeListener; private OnKeyListener mTabKeyListener; public MyTabHostLayout(Context context) { super(context); // TODO Auto-generated constructor stub } public MyTabHostLayout(Context context, AttributeSet attrs) { super(context, attrs); //initTabHost(); } public void setCurrentTab(int index){ if (index < 0 || index >= mTabSpecs.size()) { return; } if (index == mCurrentTab) { return; } // notify old tab content if (mCurrentTab != -1) { mTabWidget.getChildAt(mCurrentTab).setSelected(false); mTabSpecs.get(mCurrentTab).mContentStrategy.tabClosed(); } final TabSpec spec = mTabSpecs.get(index); // Call the tab widget's focusCurrentTab(), instead of just // selecting the tab. //mTabWidget.focusCurrentTab(mCurrentTab); final int oldTab = mCurrentTab; // set the tab //setCurrentTab(index); //mSelectedTab = index; mTabWidget.getChildAt(index).setSelected(true); //mStripMoved = true; // change the focus if applicable. if (oldTab != index) { mTabWidget.getChildAt(index).requestFocus(); } mCurrentTab = index; // tab content mCurrentView = spec.mContentStrategy.getContentView(); if (mCurrentView.getParent() == null) { mTabContent .addView( mCurrentView, new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } if (!mTabWidget.hasFocus()) { // if the tab widget didn't take focus (likely because we're in touch mode) // give the current tab content view a shot mCurrentView.requestFocus(); } //mTabContent.requestFocus(View.FOCUS_FORWARD); invokeOnTabChangeListener(); } private void invokeOnTabChangeListener() { // TODO Auto-generated method stub //mOnTabChangeListener.onTabChanged(mCurrentTab); if (mOnTabChangeListener != null) { mOnTabChangeListener.onTabChanged(getCurrentTabTag()); } } private String getCurrentTabTag() { // TODO Auto-generated method stub if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) { return mTabSpecs.get(mCurrentTab).getTag(); } return null; } public void setOnTabChangedListener(OnTabChangeListener l) { // TODO Auto-generated method stub mOnTabChangeListener = l; } public void setup() { // TODO Auto-generated method stub mTabWidget = (LinearLayout)findViewById(R.id.tabs); if (mTabWidget == null) { throw new RuntimeException( "Your MyTabHostLayout must have a TabWidget that id :R.id.tabs"); } mTabKeyListener = new OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_RIGHT: case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_DOWN: case KeyEvent.KEYCODE_ENTER: return false; } mTabContent.requestFocus(View.FOCUS_FORWARD); return mTabContent.dispatchKeyEvent(event); } }; mTabContent = (FrameLayout) findViewById(R.id.tabcontent); if (mTabContent == null) { throw new RuntimeException( "Your MyTabHostLayout must have a FrameLayout that id:R.id.tabcontent"); } } public void setup(LocalActivityManager activityGroup) { // TODO Auto-generated method stub setup(); mLocalActivityManager = activityGroup; } public LinearLayout getTabWidget() { // TODO Auto-generated method stub return mTabWidget; } public TabSpec newTabSpec(String string) { // TODO Auto-generated method stub return new TabSpec(string); } private View.OnClickListener onTabSpecClickListener = new View.OnClickListener(){ public void onClick(View v) { // TODO Auto-generated method stub Log.i("onTabSpecClickListener", ""+v.getClass()); setCurrentTab(getTabIdByView(v)); } }; private int getTabIdByView(View v) { // TODO Auto-generated method stub for (int i = 0;i <mTabWidget.getChildCount();i++){ if (v == mTabWidget.getChildAt(i)){ Log.i("change tag", "click tag id:"+i); return i; } } return 0; } public void addTab(TabSpec tabSpec) { // TODO Auto-generated method stub if (tabSpec.mIndicatorStrategy == null) { throw new IllegalArgumentException("you must specify a way to create the tab indicator."); } if (tabSpec.mContentStrategy == null) { throw new IllegalArgumentException("you must specify a way to create the tab content"); } View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView(); tabIndicator.setOnKeyListener(mTabKeyListener); tabIndicator.setOnClickListener(onTabSpecClickListener); // If this is a custom view, then do not draw the bottom strips for // the tab indicators. if (tabSpec.mIndicatorStrategy instanceof ViewIndicatorStrategy) { //mTabWidget.setStripEnabled(false); //invalidate(); } mTabWidget.addView(tabIndicator); mTabSpecs.add(tabSpec); if (mCurrentTab == -1) { setCurrentTab(0); } } public int getCurrentTab() { // TODO Auto-generated method stub return mCurrentTab; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); final ViewTreeObserver treeObserver = getViewTreeObserver(); if (treeObserver != null) { treeObserver.addOnTouchModeChangeListener(this); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); final ViewTreeObserver treeObserver = getViewTreeObserver(); if (treeObserver != null) { treeObserver.removeOnTouchModeChangeListener(this); } } public void onTouchModeChanged(boolean isInTouchMode) { if (!isInTouchMode) { // leaving touch mode.. if nothing has focus, let's give it to // the indicator of the current tab if (mCurrentView != null && (!mCurrentView.hasFocus() || mCurrentView.isFocused())) { mTabWidget.getChildAt(mCurrentTab).requestFocus(); } } } /** * A tab has a tab indicator, content, and a tag that is used to keep * track of it. This builder helps choose among these options. * * For the tab indicator, your choices are: * 1) set a label * 2) set a label and an icon * * For the tab content, your choices are: * 1) the id of a {@link View} * 2) a {@link TabContentFactory} that creates the {@link View} content. * 3) an {@link Intent} that launches an {@link android.app.Activity}. */ public class TabSpec { private String mTag; private IndicatorStrategy mIndicatorStrategy; private ContentStrategy mContentStrategy; private TabSpec(String tag) { mTag = tag; } /* *//** * Specify a label as the tab indicator. *//* public TabSpec setIndicator(CharSequence label) { mIndicatorStrategy = new LabelIndicatorStrategy(label); return this; }*/ /** * Specify a label and icon as the tab indicator. */ public TabSpec setIndicator(CharSequence label, Drawable icon) { mIndicatorStrategy = new LabelAndIconIndicatorStrategy(label, icon); return this; } /* *//** * Specify a view as the tab indicator. *//* public TabSpec setIndicator(View view) { mIndicatorStrategy = new ViewIndicatorStrategy(view); return this; }*/ /* *//** * Specify the id of the view that should be used as the content * of the tab. *//* public TabSpec setContent(int viewId) { mContentStrategy = new ViewIdContentStrategy(viewId); return this; } *//** * Specify a {@link android.widget.TabHost.TabContentFactory} to use to * create the content of the tab. *//* public TabSpec setContent(TabContentFactory contentFactory) { mContentStrategy = new FactoryContentStrategy(mTag, contentFactory); return this; }*/ /** * Specify an intent to use to launch an activity as the tab content. */ public TabSpec setContent(Intent intent) { mContentStrategy = new IntentContentStrategy(mTag, intent); return this; } public String getTag() { return mTag; } } /** * Specifies what you do to create a tab indicator. */ private static interface IndicatorStrategy { /** * Return the view for the indicator. */ View createIndicatorView(); } /** * Specifies what you do to manage the tab content. */ private static interface ContentStrategy { /** * Return the content view. The view should may be cached locally. */ View getContentView(); /** * Perhaps do something when the tab associated with this content has * been closed (i.e make it invisible, or remove it). */ void tabClosed(); } /* *//** * How to create a tab indicator that just has a label. *//* private class LabelIndicatorStrategy implements IndicatorStrategy { private final CharSequence mLabel; private LabelIndicatorStrategy(CharSequence label) { mLabel = label; } public View createIndicatorView() { final Context context = getContext(); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View tabIndicator = inflater.inflate(R.layout.tab_indicator, mTabWidget, // tab widget is the parent false); // no inflate params final TextView tv = (TextView) tabIndicator.findViewById(R.id.title); tv.setText(mLabel); if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) { // Donut apps get old color scheme tabIndicator.setBackgroundResource(R.drawable.tab_indicator_v4); tv.setTextColor(context.getResources().getColorStateList(R.color.tab_indicator_text_v4)); } return tabIndicator; } }*/ /** * How we create a tab indicator that has a label and an icon */ private class LabelAndIconIndicatorStrategy implements IndicatorStrategy { private final CharSequence mLabel; private final Drawable mIcon; private LabelAndIconIndicatorStrategy(CharSequence label, Drawable icon) { mLabel = label; mIcon = icon; } public View createIndicatorView() { final Context context = getContext(); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View tabIndicator = inflater.inflate(R.layout.tab_indicator, mTabWidget, // tab widget is the parent false); // no inflate params final TextView tv = (TextView) tabIndicator.findViewById(R.id.tabtitle); tv.setText(mLabel); final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.tabicon); iconView.setImageDrawable(mIcon); /* if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) { // Donut apps get old color scheme tabIndicator.setBackgroundResource(R.drawable.tab_indicator_v4); tv.setTextColor(context.getResources().getColorStateList(R.color.tab_indicator_text_v4)); }*/ return tabIndicator; } } /** * How to create a tab indicator by specifying a view. */ private class ViewIndicatorStrategy implements IndicatorStrategy { private final View mView; private ViewIndicatorStrategy(View view) { mView = view; } public View createIndicatorView() { return mView; } } /** * How to create the tab content via a view id. */ private class ViewIdContentStrategy implements ContentStrategy { private final View mView; private ViewIdContentStrategy(int viewId) { mView = mTabContent.findViewById(viewId); if (mView != null) { mView.setVisibility(View.GONE); } else { throw new RuntimeException("Could not create tab content because " + "could not find view with id " + viewId); } } public View getContentView() { mView.setVisibility(View.VISIBLE); return mView; } public void tabClosed() { mView.setVisibility(View.GONE); } } /** * How tab content is managed using {@link TabContentFactory}. */ private class FactoryContentStrategy implements ContentStrategy { private View mTabContent; private final CharSequence mTag; private TabContentFactory mFactory; public FactoryContentStrategy(CharSequence tag, TabContentFactory factory) { mTag = tag; mFactory = factory; } public View getContentView() { if (mTabContent == null) { mTabContent = mFactory.createTabContent(mTag.toString()); } mTabContent.setVisibility(View.VISIBLE); return mTabContent; } public void tabClosed() { mTabContent.setVisibility(View.GONE); } } /** * How tab content is managed via an {@link Intent}: the content view is the * decorview of the launched activity. */ private class IntentContentStrategy implements ContentStrategy { private final String mTag; private final Intent mIntent; private View mLaunchedView; private IntentContentStrategy(String tag, Intent intent) { mTag = tag; mIntent = intent; } public View getContentView() { if (mLocalActivityManager == null) { throw new IllegalStateException("Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?"); } final Window w = mLocalActivityManager.startActivity( mTag, mIntent); final View wd = w != null ? w.getDecorView() : null; if (mLaunchedView != wd && mLaunchedView != null) { if (mLaunchedView.getParent() != null) { mTabContent.removeView(mLaunchedView); } } mLaunchedView = wd; // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activities for now so they can get // focus if none of their children have it. They need focus to be able to // display menu items. // // Replace this with something better when Bug 628886 is fixed... // if (mLaunchedView != null) { mLaunchedView.setVisibility(View.VISIBLE); mLaunchedView.setFocusableInTouchMode(true); ((ViewGroup) mLaunchedView).setDescendantFocusability( FOCUS_AFTER_DESCENDANTS); } return mLaunchedView; } public void tabClosed() { if (mLaunchedView != null) { mLaunchedView.setVisibility(View.GONE); } } } /** * Makes the content of a tab when it is selected. Use this if your tab * content needs to be created on demand, i.e. you are not showing an * existing view or starting an activity. */ public interface TabContentFactory { /** * Callback to make the tab contents * * @param tag * Which tab was selected. * @return The view to display the contents of the selected tab. */ View createTabContent(String tag); } /** * Interface definition for a callback to be invoked when tab changed */ public interface OnTabChangeListener { void onTabChanged(String tabId); } } 工程详见附件
- TabHostDemo.zip (112.6 KB)
- 下载次数: 245
评论
2 楼
xiangdream
2012-04-17
强 。。。。。。。
1 楼
oubaoxingfu
2012-03-15
很不错,我有个问题不明白,每一个tab的背景颜色和字体在点击的时候会有变化,这个功能是在哪里实现的,请教,289982659@qq.com
发表评论
-
百度坐标与GPS坐标转换
2014-08-06 15:37 31495官网这么说的 4.3 百度坐标为何有偏移? 国际 ... -
仿网易新闻App
2014-02-25 14:29 1786最近项目更换了新的设计,实现了左右滑动、下拉刷新的 ... -
Android图片压缩
2014-01-17 10:45 912比较简单,直接上代码 public static ... -
方便实用的下拉刷新控件,支持ScrollView、AbsListView
2013-07-10 11:23 20495最近要做一个下拉刷新的功能,网上找了很多例子,也看了一些开 ... -
Android根据指定的尺寸加载Bitmap
2013-04-15 15:28 10968因为图片的尺寸千差百异,要想加载不同的图片,又要保证不影响整 ... -
Wifi层次结构状态机(一)
2012-03-06 13:32 1872Android2.3中Wifi的状态都是在WifiStateT ... -
来电上报流程
2011-07-26 15:26 1556最近项目在做一个双模手机,我负责电话框架层的移植,因此把2.3 ... -
Messenger:使用消息的跨进程通信
2011-06-29 15:07 7712Messenger:信使 官方文档解释:它引用了一个Hand ... -
Android MediaPlayer的生命周期
2011-06-27 16:46 1547Android MediaPlayer 的生 ... -
AsyncQueryHandler的理解
2011-06-20 19:42 7951每天进步一点点之AsyncQueryHandler学习 As ... -
Phone去电请求及响应(framework层)
2011-06-02 16:58 1978打电话请求流程 1.进入键盘界面(TwelvekeyDiale ... -
去电流程
2011-05-27 17:10 1435去电流程: 广播:action="android.i ... -
Android Aidl机制
2011-05-27 14:44 2389Aidl机制提供进程间传递对象。 当然在进程间传递对象也可以使 ... -
转:android Menu理解
2011-05-12 20:56 2579学了较长时间的android. 有些东西都习以为常,不愿意去深 ... -
Android中如何调用其它应用
2011-05-05 19:40 1868每天进步一点点 Android中如何调用其它应用 如:我 ... -
ContentProvider
2011-04-29 17:14 1277每天进步一点 MyContentProvider extend ... -
AutoCompleteTextView
2011-04-29 16:54 1191每天成长一点 AutoCompleteTextView的适配器 ...
相关推荐
通过分析这些文件,我们可以学习如何动态地创建和管理两个级别的TabHost,以及如何在不同标签间切换时更新内容。 总结来说,Android的嵌套TabHost是一种增强用户界面的方法,它允许开发者创建更复杂的导航结构,...
在Android开发中,TabHost是一个非常重要的组件,用于创建具有多个选项卡的用户界面,每个选项卡都可以展示不同的...通过学习本资源提供的案例和文档,开发者可以更好地掌握TabHost的用法,从而提升应用的用户体验。
这篇博客文章“android总结之TabHost”深入探讨了如何在Android应用中使用TabHost进行界面设计。TabHost提供了在同一个屏幕上展示多个功能区域的能力,使得用户可以方便地切换不同内容。 首先,我们需要理解TabHost...
总结,TabHost是Android开发中实现多Tab界面的经典组件,虽然在新版本的Android中,更多地推荐使用ViewPager和TabLayout的组合,但对于理解Android的历史和各种实现方式,TabHost仍然是不可或缺的一部分。通过学习和...
一直想仿一个微博的界面,最近写了个演示代码。 ... 从这个资源开始,资源分以后为0.当初上传资源其实为了换点积分,但是最近发现违背了初衷,我也好多次因为没有分,导致下不了东西。所以以后就尽力写一些免费的资源...
总结来说,仿新浪微博的TabHost实现涉及布局设计、TabHost初始化、自定义TabWidget样式以及处理每个标签页的逻辑。通过学习这个示例,开发者可以更好地掌握Android中的TabHost用法,从而创建出更加丰富和用户友好的...
这篇博客“android tabhost --android UI 学习”很可能深入探讨了如何使用TabHost来构建一个多页面的应用程序布局。在Android开发中,TabHost通常结合TabWidget和FrameLayout一起使用,前者负责显示和管理标签,后者...
通过学习和理解这个样例,开发者可以灵活地根据应用需求调整TabHost的位置和样式,提升用户体验。 总结来说,自定义Android TabHost的标签位置是一项涉及布局参数调整和样式定制的工作。通过理解TabHost的工作原理...
总结,Android TabHost是构建多视图应用程序的强大工具,它允许用户在一个界面上轻松切换不同功能。通过学习和实践,开发者可以掌握如何配置和定制TabHost,从而提升应用的用户体验。在提供的源码实例中,你可以找到...
总结来说,虽然现代Android开发倾向于使用Fragment替代ActivityGroup,但理解TabHost和ActivityGroup的历史以及它们的工作方式对于深入学习Android系统和历史演进非常重要。通过对"Android TabHost内嵌ActivityGroup...
总结来说,这个压缩包提供的源码是关于如何在Android应用中使用ViewPager和TabHost实现可滑动的标签页,这对于开发复杂的多视图应用程序非常有用。通过学习和理解这个示例,开发者可以提升自己在Android UI设计和...
总结一下,自定义TabWidget的TabHost涉及到的关键点有:设置TabHost和TabWidget的布局,初始化TabHost,创建并添加选项卡,以及可能的外观定制。通过这些步骤,开发者可以创建出符合应用需求的个性化选项卡界面,...
总结,"仿新浪微博TabHost菜单"的实现涉及Android的布局管理、Intent机制、自定义视图以及事件监听等多个方面。开发者需要熟练掌握这些基础知识,才能创建出富有个性和用户体验良好的App界面。通过这个特效集锦系列...
总结一下,这个DEMO展示了如何使用`TabHost`创建一个带有底部选项卡的界面,包括设置布局、初始化`TabHost`、创建`TabSpec`以及处理标签切换事件。尽管`TabHost`在现代Android开发中已不常用,但它仍然是Android开发...
总结来说,`TabHost` 是 Android 开发早期常用于实现多标签页界面的组件,虽然现在有更多现代化的替代方案,但理解其工作原理对于开发者而言仍然有价值。通过 "Tabhost 练习" 这样的项目,你可以巩固基础知识,并...
总结一下,`TabHost`是Android中创建多标签界面的工具,通过`TabWidget`和`FrameLayout`来实现标签的显示和内容的切换。虽然现在有更多现代化的选择,但掌握`TabHost`的基本用法对理解Android界面设计仍然非常重要。...
总结来说,`TabHost`是一个用于构建多标签界面的组件,而`TabHostWithAnim`资源着重展示了如何添加切换动画,提升用户体验。通过学习这部分内容,开发者不仅可以掌握`TabHost`的基本用法,还能了解到如何利用动画...
总结来说,这个压缩包提供的源码示例可以帮助开发者理解如何将`ViewPager`的滑动功能和`TabHost`的标签导航相结合,实现一个既美观又实用的Android应用界面。通过研究源码,可以学习到如何自定义`PagerAdapter`、...
总结来说,本文介绍了如何在Android中实现两种特殊的TabHost,包括模仿网易新闻底部导航栏的FragmentTabHost实现以及自定义TabWidget的方法。通过这些知识,开发者可以创造出更具交互性和视觉吸引力的Android应用。