【背景】
折腾:
期间,需要在创建好的tab页面内,不依赖于xml文件设置布局,动态创建多个Group分组。
【折腾过程】
1.弄了半天,感觉对于Android中的UI架构不熟悉,一头雾水。
所以去看官网中关于UI架构的解释:
UI Overview | Android Developers
后来用如下代码:
public class MainActivity extends FragmentActivity { //public class MainActivity extends Activity { //public class MainActivity extends TabActivity { /** * The serialization (saved instance state) Bundle key representing the * current tab position. */ private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item"; // @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //TabHost tabHost2 = getTabHost(); TabHost tabHost=(TabHost)findViewById(R.id.tabHost); tabHost.setup(); TabSpec spec1=tabHost.newTabSpec("Tab1"); //spec1.setContent(R.id.tab1); spec1.setContent(new TabHost.TabContentFactory() { public View createTabContent(String tag) { // TextView txtView = new TextView(MainActivity.this); // txtView.setText("Tab Text in createTabContent"); // return txtView;\ LinearLayout tab1AllGroup = new LinearLayout(MainActivity.this); tab1AllGroup.setLayoutParams( new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); tab1AllGroup.setOrientation(LinearLayout.VERTICAL); // //LinearLayout panel = (LinearLayout) findViewById(R.id.eachTab); LinearLayout tab1Group1 = new LinearLayout(MainActivity.this); tab1Group1.setLayoutParams( new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group1.setOrientation(LinearLayout.VERTICAL); TextView tab1Group1Text1 = new TextView(MainActivity.this); tab1Group1Text1.setText("This is newly created tab: Tab 1 Group 1 Text 1"); tab1Group1Text1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 60)); tab1Group1.addView(tab1Group1Text1); TextView tab1Group1Text2 = new TextView(MainActivity.this); tab1Group1Text2.setText("This is newly created tab: Tab 1 Group 1 Text 2"); tab1Group1Text2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group1.addView(tab1Group1Text2); // login button final Button btnLogin = new Button(MainActivity.this); btnLogin.setText("Login"); btnLogin.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); btnLogin.setGravity(Gravity.CENTER); btnLogin.setOnClickListener( new View.OnClickListener() { public void onClick(View view) { Log.d("pocketmagic.net", "_createForm click but"); } }); tab1Group1.addView(btnLogin); LinearLayout tab1Group2 = new LinearLayout(MainActivity.this); tab1Group2.setLayoutParams( new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group2.setOrientation(LinearLayout.VERTICAL); TextView tab1Group2Text1 = new TextView(MainActivity.this); tab1Group2Text1.setText("This is newly created tab: Tab 1 Group 2 Text 1"); tab1Group2Text1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 60)); tab1Group2.addView(tab1Group2Text1); tab1AllGroup.addView(tab1Group1); tab1AllGroup.addView(tab1Group2); return tab1AllGroup; } }); spec1.setIndicator("Tab Text for setIndicator"); TabSpec spec2=tabHost.newTabSpec("Tab2"); spec2.setIndicator("Tab 2"); spec2.setContent(new TabHost.TabContentFactory() { public View createTabContent(String tag) { // return(new AnalogClock(MainActivity.this)); LinearLayout panel = new LinearLayout(MainActivity.this); panel.setLayoutParams( new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); panel.setOrientation(LinearLayout.VERTICAL); //LinearLayout panel = (LinearLayout) findViewById(R.id.eachTab); TextView tab2Text1 = new TextView(MainActivity.this); tab2Text1.setText("This is newly created tab: Tab 2 Text 1"); tab2Text1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); panel.addView(tab2Text1); return panel; } }); spec2.setIndicator("Tab 2"); tabHost.addTab(spec1); tabHost.addTab(spec2); }
对应xml文件:
res/layout/activity_main.xml
的内容是:
<?xml version="1.0" encoding="utf-8"?> <!-- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" tools:ignore="MergeRootFrame" /> --> <TabHost android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tabHost" xmlns:android="http://schemas.android.com/apk/res/android"> <TabWidget android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/tabs"/> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@android:id/tabcontent"> <!-- <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/eachTab" android:orientation="vertical" android:paddingTop="60px"> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/tab1" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab1" android:id="@+id/txt1"/> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab2" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab 2" android:id="@+id/txt2"/> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab3" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab 3" android:id="@+id/txt3"/> </LinearLayout> --> </FrameLayout> </TabHost>
是可以动态添加多个group:
和:
但是很明显存在很多问题:
(1)显示出来的内容,不是在tab内,而是在整个页面内
(2)多个group中间也是没有分隔开的。
3.现在先整理和记录一些心得:
问题1:找不到getTabHost
如果你的activity的类,不是继承自TabActivity,那么直接用getTabHost,则会提示你找不到此函数。
比如:
public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TabHost tabHost2 = getTabHost();
只有改为:
//public class MainActivity extends FragmentActivity { public class MainActivity extends TabActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TabHost tabHost2 = getTabHost();
才可以找到getTabHost。
问题2:最好不要再用TabActivity
上面的错误的该法,虽然是可以正常编译通过,但是不是好的做法。
以为你TabActivity现在已经废弃,不推荐再使用了。
参考:
Android之TabHost – 好寂寞先生 – 51CTO技术博客
问题3:Your TabHost must have a FrameLayout whose id attribute is ‘android.R.id.tabcontent’
如果你之前的Tab对应的xml定义中,缺少了对应的FrameLayout的tabcontent部分,比如:
<?xml version="1.0" encoding="utf-8"?> <TabHost android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tabHost" xmlns:android="http://schemas.android.com/apk/res/android"> <TabWidget android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/tabs"/> <!-- <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@android:id/tabcontent"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/eachTab" android:orientation="vertical" android:paddingTop="60px"> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/tab1" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab1" android:id="@+id/txt1"/> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab2" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab 2" android:id="@+id/txt2"/> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab3" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab 3" android:id="@+id/txt3"/> </LinearLayout> </FrameLayout> --> </TabHost>
则运行时,会出现异常:
02-27 16:54:43.642: W/dalvikvm(15932): threadid=1: thread exiting with uncaught exception (group=0x41abce10) 02-27 16:54:43.662: E/AndroidRuntime(15932): FATAL EXCEPTION: main 02-27 16:54:43.662: E/AndroidRuntime(15932): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mm.harthandheld/com.mm.harthandheld.UI.MainActivity}: java.lang.RuntimeException: Your TabHost must have a FrameLayout whose id attribute is 'android.R.id.tabcontent' 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2245) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2295) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.ActivityThread.access$700(ActivityThread.java:150) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1280) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.os.Handler.dispatchMessage(Handler.java:99) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.os.Looper.loop(Looper.java:176) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.ActivityThread.main(ActivityThread.java:5279) 02-27 16:54:43.662: E/AndroidRuntime(15932): at java.lang.reflect.Method.invokeNative(Native Method) 02-27 16:54:43.662: E/AndroidRuntime(15932): at java.lang.reflect.Method.invoke(Method.java:511) 02-27 16:54:43.662: E/AndroidRuntime(15932): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102) 02-27 16:54:43.662: E/AndroidRuntime(15932): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869) 02-27 16:54:43.662: E/AndroidRuntime(15932): at dalvik.system.NativeStart.main(Native Method) 02-27 16:54:43.662: E/AndroidRuntime(15932): Caused by: java.lang.RuntimeException: Your TabHost must have a FrameLayout whose id attribute is 'android.R.id.tabcontent' 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.widget.TabHost.setup(TabHost.java:170) 02-27 16:54:43.662: E/AndroidRuntime(15932): at com.mm.harthandheld.UI.MainActivity.onCreate(MainActivity.java:97) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.Activity.performCreate(Activity.java:5267) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1097) 02-27 16:54:43.662: E/AndroidRuntime(15932): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2209) 02-27 16:54:43.662: E/AndroidRuntime(15932): ... 11 more
而把对应的FrameLayout的tabcontent加上,即可:
<?xml version="1.0" encoding="utf-8"?> <TabHost android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tabHost" xmlns:android="http://schemas.android.com/apk/res/android"> <TabWidget android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/tabs"/> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@android:id/tabcontent"> <!-- <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/eachTab" android:orientation="vertical" android:paddingTop="60px"> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/tab1" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab1" android:id="@+id/txt1"/> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab2" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab 2" android:id="@+id/txt2"/> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab3" android:orientation="vertical" android:paddingTop="60px"> <TextView android:layout_width="fill_parent" android:layout_height="100px" android:text="This is tab 3" android:id="@+id/txt3"/> </LinearLayout> --> </FrameLayout> </TabHost>
可参考:
Android TabHost,TabWidget选项卡总结-Android开发问题解答-eoe Android开发者社区_Android开发论坛 – Powered by Discuz!
TabWidget/TabHost的两种使用方法 – 榴莲酥博客 – eoe移动开发者社区
问题4:TabHost,TabWidget,Tab content,FrameLayout之间的关系
可以参考:
TabView (Part 1) – Simple tab control in Android | Android Tech(需要翻墙)
和:
对TabHost、TabWidget的理解分析 – Alex_Michel – 51CTO技术博客
【继续折腾】
1.另外想起来了,此处应该是去找Android中的类似于Windows中的GroupBox的东西的。
所以再去搜:
android groupbox
2.找到:
Android: how to make a GroupBox widget? – Stack Overflow
找到这个讨论:
Border around a LinearLayout / rounded edges – Google Groups
但是没用。
原先帖子中,有人自己用代码模拟了一个,但是狂复杂。。。
3.参考:
android 布局,有没有类似mfc 中groupbox的控件-CSDN论坛-CSDN.NET-中国最大的IT技术社区
去找找
android CheckBoxPreference
找到:
官网的:
CheckBoxPreference | Android Developers
其他的示例:
Android的设置界面及Preference使用 – ichliebephone的专栏 – 博客频道 – CSDN.NET
很明显,不是所希望的groupbox的效果。。。
4.真是忍不住吐槽,Android中竟然不内置支持GroupBox这种控件。。。
5.参考:
Border around a LinearLayout / rounded edges – Google Groups
提到的:
how to put a border around an android textview – Stack Overflow
有空再去试试效果,最后弄出个基本的效果:
(1)添加xml去配置背景
在项目的/res/drawable下面加上一个group_background.xml
内容为:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="#ff0000" /> <stroke android:width="3dip" android:color="#4fa5d5"/> </shape>
(2)在原先的代码中,添加对应的setBackgroundResource
此处,是参考:
how to put a border around an android textview – Stack Overflow
而去找了官方的:
中的:
android:background setBackgroundResource(int) A drawable to use as the background. |
而发现,我对于View类的东西(此处的我的是LinearLayout)除了可以静态的在xml中配置对应的android:background的属性之外,也可以动态的通过代码setBackgroundResource去设置的。
代码为:
LinearLayout tab1Group1 = new LinearLayout(tabContext); tab1Group1.setLayoutParams( new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group1.setOrientation(LinearLayout.VERTICAL); tab1Group1.setBackgroundResource(R.drawable.group_background);
然后运行效果如下:
其中可见:
此处背景色故意设置为了红色,边框是淡蓝色。
算是基本模拟出来外部有边框的groupbox的效果了。。。
6.再去新建多个groupbox试试,但是用如下代码:
final TabHost tabHost = (TabHost)findViewById(R.id.tabHost); tabHost.setup(); //final Context tabContext = tabHost.getContext(); final Context tabContext = MainActivity.this; TabSpec spec1=tabHost.newTabSpec("Tab1"); //spec1.setContent(R.id.tab1); spec1.setContent(new TabHost.TabContentFactory() { public View createTabContent(String tag) { // TextView txtView = new TextView(tabContext); // txtView.setText("Tab Text in createTabContent"); // return txtView;\ // LinearLayout tab1AllGroup = new LinearLayout(tabContext); // tab1AllGroup.setLayoutParams( // new LayoutParams( // LayoutParams.FILL_PARENT, // LayoutParams.WRAP_CONTENT)); // tab1AllGroup.setOrientation(LinearLayout.VERTICAL); FrameLayout tab1AllGroup = (FrameLayout) findViewById(android.R.id.tabcontent); //LinearLayout panel = (LinearLayout) findViewById(R.id.eachTab); LinearLayout tab1Group1 = new LinearLayout(tabContext); tab1Group1.setLayoutParams( new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group1.setOrientation(LinearLayout.VERTICAL); tab1Group1.setBackgroundResource(R.drawable.group_background); TextView tab1Group1Text1 = new TextView(tabContext); tab1Group1Text1.setText("This is newly created tab: Tab 1 Group 1 Text 1"); //tab1Group1Text1.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 60)); tab1Group1.addView(tab1Group1Text1); TextView tab1Group1Text2 = new TextView(tabContext); tab1Group1Text2.setText("This is newly created tab: Tab 1 Group 1 Text 2"); //tab1Group1Text2.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group1.addView(tab1Group1Text2); LinearLayout tab1Group2 = new LinearLayout(tabContext); tab1Group2.setLayoutParams( new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group2.setOrientation(LinearLayout.VERTICAL); tab1Group2.setBackgroundResource(R.drawable.group_background); // login button final Button btnLogin = new Button(tabContext); btnLogin.setText("Login"); btnLogin.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); btnLogin.setGravity(Gravity.CENTER); btnLogin.setOnClickListener( new View.OnClickListener() { public void onClick(View view) { Log.d("pocketmagic.net", "_createForm click but"); } }); tab1Group2.addView(btnLogin); LinearLayout tab1Group3 = new LinearLayout(tabContext); tab1Group3.setLayoutParams( new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); tab1Group3.setOrientation(LinearLayout.VERTICAL); TextView tab1Group2Text1 = new TextView(tabContext); tab1Group2Text1.setText("This is newly created tab: Tab 1 Group 2 Text 1"); tab1Group2Text1.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 60)); tab1Group3.addView(tab1Group2Text1); tab1AllGroup.addView(tab1Group1); tab1AllGroup.addView(tab1Group2); tab1AllGroup.addView(tab1Group3); return tab1AllGroup; } }); spec1.setIndicator("Tab 1"); TabSpec spec2=tabHost.newTabSpec("Tab2"); spec2.setIndicator("Tab 2"); spec2.setContent(new TabHost.TabContentFactory() { public View createTabContent(String tag) { // return(new AnalogClock(tabContext)); LinearLayout panel = new LinearLayout(tabContext); panel.setLayoutParams( new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); panel.setOrientation(LinearLayout.VERTICAL); //LinearLayout panel = (LinearLayout) findViewById(R.id.eachTab); TextView tab2Text1 = new TextView(tabContext); tab2Text1.setText("This is newly created tab: Tab 2 Text 1"); tab2Text1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); panel.addView(tab2Text1); return panel; } }); spec2.setIndicator("Tab 2"); tabHost.addTab(spec1); tabHost.addTab(spec2); }
结果是:
tab内的多个group,全部都重叠了。搞得只能看到最后一层的内容。
【总结】
算了,很明显,实际上此处新建多个group已经解决了。
但是显示很错乱,那是由于之前就存在的问题:
【未解决】Android中的TabHost中的TAB中的FrameLayout中的View出现重叠且覆盖了TAB标签
转载请注明:在路上 » 【已解决】android中在Tab页面中动态创建多个Group