>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 18965 个阅读者 刷新本主题
 * 贴子主题:  Android之TabHost 回复文章 点赞(0)  收藏  
作者:sunshine    发表时间:2020-05-15 05:08:36     消息  查看  搜索  好友  邮件  复制  引用

   想要制作出拥有多个Tab相互切换的界面,需要用到几个主要的组件:

1. android.app.TabActivity;

2. android.widget.TabHost;

3. android.view.LayoutInflater;

4.  android.widget.TabWidget

5. android.widget.FrameLayout

  本文描述了制作Tabs界面的三种常用方法,参考来自于Android官方文档及ApiDemo。

  在此需要特别说明:android.app.TabActivity;在api13已经被视为废弃组件,官方推荐使用  android.app.Fragment,但是如果为了兼容低版本设备,则可以使用 v4 support library提供的fragment api。

   即便如此,预先学习一下旧式的TabActivity,也能更好地学习Fragment。

   效果图和示例代码:

1.主界面

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".MainActivity" >

    <ListView

        android:id="@+id/lstv_demos"

        android:layout_width="match_parent"

        android:layout_height="match_parent" />

</RelativeLayout>

MainActivity.java

package com.panny.tabsdemo;

import android.os.Bundle;

import android.app.Activity;

import android.content.Intent;

import android.view.View;

import android.view.Window;

import android.view.WindowManager;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.ListView;

public class MainActivity extends Activity {

      private ListView lstvDemos;
      private String[] contents = new String[]{

            "Content By Id",

            "Content By Factory",

            "Content By Intent",

            "Scrollable"};

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_main);

       this.lstvDemos = (ListView) findViewById(R.id.lstv_demos);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(

                getCurrentContext(),

                android.R.layout.simple_list_item_1,

                contents);

        this.lstvDemos.setAdapter(adapter);

         this.lstvDemos.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override

            public void onItemClick(AdapterView<?> parent, View view,

                    int position, long id) {

                switch (position) {

                case 0:

                    startActivity(new Intent(getCurrentContext(), ContentByIdActivity.class));

                    break;

                case 1:

                    startActivity(new Intent(getCurrentContext(), TabByContentFactoryActivity.class));

                    break;

                case 2:

                    startActivity(new Intent(getCurrentContext(), TabByIntentActivity.class));

                    break;

                case 3:

                    startActivity(new Intent(getCurrentContext(), ScrollableActivity.class));

                    break;

                default:

                    break;

                }

          }

        });

    }

        private MainActivity getCurrentContext() {

        return MainActivity.this;

    }

}

2.Content By Id

   点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

ContentByIdActivity.java

package com.panny.tabsdemo;

import android.os.Bundle;

import android.app.TabActivity;

import android.content.Context;

import android.view.LayoutInflater;

import android.widget.TabHost;

public class ContentByIdActivity extends TabActivity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

         /*

         * TabHost作为标签窗体试图的容器。

         * 这个对象包含两个元素,第一个是一个包含了若干个标签名称的集合,用户通过点击它来切换标签视图;

         * 第二个是一个帧布局对象,用于显示被选中标签的内容。

         * 实际上它们是相互映射,并且相互独立的,但是它们的内容均由TabHost容器控制,而非它们自身。

         */


        TabHost tabHost = getTabHost(); // 如果用户没有自定义id为@android:id/tabhost的<TabHost/>,那么将自动从系统获取。

        /*

         * 首先通过系统服务获取已经在当前上下文挂载并且与设备配置好的LayoutInflater实例

         * 这一点必须讲究一下,因为某些文档会直接使用:LayoutInflater.from(this).inflate(...)

         * 虽然这并不影响运行效果,但是可能会有部分性能消耗,即使不是很大,但我们也应该注意。

         */


        LayoutInflater inflter = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        /*

         * LayoutInflater的作用是将layout布局文件转换成为View实例,正如第一个参数所为;

         * 第二个参数的作用是把tabHost.getTabContentView()得到的FrameLayout实例作为root;

         * 第三个参数的作用是将第一个参数的View挂载在root下。

         */


        inflter.from(getCurrentContext()).inflate(R.layout.activity_content_by_id, tabHost.getTabContentView(), true);

                                                                                                                             /*

         * TabHost实例负责控制tab增减

         * (1)创建一个标签空间,名称为tab01,但它不用于显示, 但它有自己的用处,可参看TabByContentFactoryActivity

         * (2)设置标签显示的名称,或许也可以添加一个背景图

         * (需要注意的是:在添加背景图使,笔者在emulator-api10 和 emulator-api17上的运行效果不同,emulator-api10可以允许同时添加label和drawable,

         * 而emulator-api17需要如此.setIndicator("", getResources().getDrawable(R.drawable.ic_launcher)))

         * (3)设置标签对应的内容

         */


        tabHost.addTab(

                tabHost.newTabSpec("tab01") // (1)

                .setIndicator("one", getResources().getDrawable(R.drawable.ic_launcher))// (2)

                .setContent(R.id.tv_view01)); // (3)

        tabHost.addTab(tabHost.newTabSpec("tab02").setIndicator("two").setContent(R.id.tv_view02));

        tabHost.addTab(tabHost.newTabSpec("tab03").setIndicator("three").setContent(R.id.tv_view03));

         }

        private ContentByIdActivity getCurrentContext() {

        return ContentByIdActivity.this;

    }

}

activity_content_by_id.xml

<FrameLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent">

   <TextView

        android:id="@+id/tv_view01"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:text="This is the view01" />

     <TextView

        android:id="@+id/tv_view02"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:text="This is the view02" />

      <TextView

        android:id="@+id/tv_view03"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:text="This is the view03" />

      </FrameLayout>  

         3.Content By Factory

  点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

  TabByContentFactoryActivity.java

package com.panny.tabsdemo;

import android.app.TabActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.TabHost;

import android.widget.TabHost.TabContentFactory;

import android.widget.TextView;

public class TabByContentFactoryActivity extends TabActivity implements TabContentFactory {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        TabHost tabHost = getTabHost();

        tabHost.addTab(

                tabHost.newTabSpec("tab01")

                .setIndicator("one")

                .setContent(this));

               tabHost.addTab(

                tabHost.newTabSpec("tab02")

                .setIndicator("two")

                .setContent(this));

               tabHost.addTab(

                tabHost.newTabSpec("tab03")

                .setIndicator("three")

                .setContent(this));

    }

    @Override

    public View createTabContent(String tag) {

        TextView tv = new TextView(this);

        tv.setText("This is the " + tag); // 这个参数来自于:tabHost.newTabSpec("tab01")

        return tv;

    }

}

          4.Content By Intent

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

  TabByIntentActivity.java

package com.panny.tabsdemo;

import android.app.TabActivity;

import android.content.Intent;

import android.os.Bundle;

import android.widget.TabHost;

public class TabByIntentActivity extends TabActivity {

     @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

                TabHost tabHost = getTabHost();

                tabHost.addTab(

                tabHost.newTabSpec("list")

                .setIndicator("list")

                .setContent(new Intent(this, Cities.class)));

                tabHost.addTab(

                tabHost.newTabSpec("photos")

                .setIndicator("photos")

                .setContent(new Intent(this, Phones.class)));
      }

}

  Cities.java

package com.panny.tabsdemo;

import android.app.ListActivity;

import android.os.Bundle;

import android.widget.ArrayAdapter;

public class Cities extends ListActivity {

           private String[] cities = new String[]{

            "ShangHai", "BeiJin", "GuangZhou",

            "ChongQing", "WuHan", "FuJian",

            "XiAn", "HeiLongJiang", "QingDao"

    };

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, cities);

        getListView().setAdapter(adapter);

    }

}

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

Phones.java

package com.panny.tabsdemo;

import java.util.ArrayList;

import android.app.ListActivity;

import android.content.Context;

import android.os.Bundle;

import android.view.View;

import android.view.ViewGroup;

import android.view.ViewGroup.LayoutParams;

import android.widget.AbsListView;

import android.widget.BaseAdapter;

import android.widget.Button;

import android.widget.ImageView;

public class Phones extends ListActivity {

    private Button btnAdd;

    private Button btnClear;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.photos_list);

        this.btnAdd = (Button) findViewById(R.id.btn_add_photo);

        this.btnClear = (Button) findViewById(R.id.btn_clear_photos);

          // 设置当listview为空时,应该显示什么视图,在此显示预先定义的TextView

        getListView().setEmptyView(findViewById(R.id.tv_empty));

         final PhotoAdapter adapter = new PhotoAdapter(this);

        setListAdapter(adapter);

        this.btnAdd.setOnClickListener(new View.OnClickListener() {

           @Override

            public void onClick(View v) {

                adapter.add();

             }

        });

        this.btnClear.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                adapter.clear();

          }

        });

}

    private class PhotoAdapter extends BaseAdapter {

        private Context mContext;

        private int[] photosPool = new int[]{

                R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3,

                R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6,

                R.drawable.sample_7

        };

        // 为了动态添加图片,它才是adapter真正的内容提供者

        private ArrayList<Integer> photos = new ArrayList<Integer>();

        public PhotoAdapter(Context mContext) {

            this.mContext = mContext;

        }

        @Override

        public int getCount() {

            return photos.size();

        }

        @Override

        public Object getItem(int position) {

            return photos.get(position);

        }

        @Override

        public long getItemId(int position) {

            return position;

        }

        @Override

        public View getView(int position, View convertView, ViewGroup parent) {

            ImageView i = new ImageView(mContext);

            i.setImageResource(photos.get(position));

            i.setAdjustViewBounds(true);

            i.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

            i.setBackgroundResource(R.drawable.picture_frame);

            return i;

        }

       private void add() {

            int wicthPic = (int) Math.round(Math.random() * (photosPool.length - 1));

            photos.add(photosPool[wicthPic]);

            notifyDataSetChanged();

        }

       private void clear() {

            photos.clear();

            notifyDataSetChanged();

        }

    }

                                                                                                                      }
  R.layout.photos_list.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >
    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal" >

        <Button

            android:id="@+id/btn_add_photo"

            android:layout_width="0dip"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="Add Photo"/>

        <Button

            android:id="@+id/btn_clear_photos"

            android:layout_width="0dip"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="Clear Photos"/>

       </LinearLayout>

    <!-- The frame layout is here since we will do showing either

    the list view or the text view when the list view is empty.  -->

    <FrameLayout

        android:layout_width="match_parent"

        android:layout_height="match_parent">

      <!-- Here is the list. Since we are using a ListActivity, we

             have to identity it as "@android:id/list" so ListActivity will

             find it -->

        <ListView

            android:id="@android:id/list"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:drawSelectorOnTop="false"/>

         <!-- Here is the view to show if the list is emtpy -->

        <TextView

            android:id="@+id/tv_empty"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:text="No photos" />

      </FrameLayout>

</LinearLayout>  

         4.Scrollable

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

  ScrollableActivity.java

package com.panny.tabsdemo;

import android.app.TabActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.TabHost;

import android.widget.TabHost.TabContentFactory;

import android.widget.TextView;

public class ScrollableActivity extends TabActivity implements TabContentFactory {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.tab_scroll); // 不要忘记加载自定义的布局文件

           TabHost tabHost = getTabHost();

            for(int i = 0; i < 30; i ++) {

            tabHost.addTab(

                    tabHost.newTabSpec("tab" + i)

                    .setIndicator("tab_" + i)

                    .setContent(this));

        }

    }

    @Override

    public View createTabContent(String tag) {

        TextView tv = new TextView(this);

        tv.setText("This is " + tag);

        return tv;

    }

}

  R.layout.tab_scroll.xml

<?xml version="1.0" encoding="utf-8"?>

<!-- Here is the root and it must be identified as @android:id/tabhost

     so that it can be found by getTabHost()-->

<TabHost

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:id="@android:id/tabhost" >

     <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="vertical"

        android:padding="5dip">

        <HorizontalScrollView

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:scrollbars="none">

        <!-- Here is the tab label container and it must be identified as @android:id/tabs

                 so that it can be found by tabhost when addTab() -->

            <TabWidget

                android:id="@android:id/tabs"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                android:gravity="center_horizontal|center_vertical" />

           </HorizontalScrollView>

        <!-- Here is the tab content container and it must be indentified as @android:id/tabcontent

             so that it could be found by tabhost when setContent() -->

        <FrameLayout

            android:id="@android:id/tabcontent"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:padding="5dip" />

           </LinearLayout>

    </TabHost>

----------------------------
原文链接:https://blog.51cto.com/pannyhjm/1265798

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-05-29 08:51:24 重新编辑]
  Java面向对象编程-->操作符
  JavaWeb开发-->使用Session(Ⅰ)
  JSP与Hibernate开发-->通过JPA API检索数据
  Java网络编程-->非阻塞通信
  精通Spring-->虚拟DOM和render()函数
  Vue3开发-->Vue CLI脚手架工具
  Android开发实践:用脚本编译Android工程
  Android OpenGL 学习笔记
  Android线程处理简述
  Android SDCard UnMounted 流程分析
  浅析Android的通知系统
  Android数据存储之Content Providers
  Android资源命名规范
  Android学习建议
  Scroll的原理和简单使用
  Android 性能优化之渲染原理
  Android性能优化:布局渲染流程及优化
  Android 活动(Activity)
  Android 之不要滥用 SharedPreferences(下)
  Android无侵入式引导提示-一键式启动
  Android——文章详情页的处理
  更多...
 IPIP: 已设置保密
树形列表:   
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。