DrawerLayout与FragmentTabHost结合模仿oschina主界面

2023-11-17

1. DrawerLayout实现侧滑菜单

drawerlayout是官方出的侧滑菜单控件,使用起来非常方便。将它当作LinearLayout一样的布局控件,完成布局xml文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawerlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="fly.drawerandtab.ui.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <FrameLayout
            android:id="@+id/realtabcontent"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"/>

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/windows_bg">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="4dip">

                    <fly.drawerandtab.widget.MyFragmentTabHost
                        android:id="@+id/tabhost"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="4dip" />

                    <View
                        android:layout_width="match_parent"
                        android:layout_height="1px"
                        android:background="?attr/lineColor" />
                </RelativeLayout>

                <ImageView
                    android:id="@+id/quick_option_iv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:clickable="true"
                    android:contentDescription="@null"
                    android:src="@drawable/btn_quickoption_selector" />
        </FrameLayout>
    </LinearLayout>

    <fragment
        android:id="@+id/left_fragment"
        android:name="fly.drawerandtab.fragment.LeftFragment"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        tools:layout="@layout/fragment_left" />

    <fragment
        android:id="@+id/right_fragment"
        android:name="fly.drawerandtab.fragment.RightFragment"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        tools:layout="@layout/fragment_right" />
</android.support.v4.widget.DrawerLayout>

一个布局控件,这里用的是LinearLayout充满父容器,两个fragment分别代表左侧滑和右侧滑,android:layout_gravity属性代表左边还是右边。
左侧滑栏的fragment代码:

package fly.drawerandtab.fragment;

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import fly.drawerandtab.R;

/**
 * Created by Fly on 2016/6/25.
 */
public class LeftFragment extends Fragment implements View.OnClickListener{
    private View mLeftView;
    private View first_item;
    private View second_item;
    private View third_item;
    private View forth_item;
    private View fifth_item;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mLeftView = inflater.inflate(R.layout.fragment_left, container, false);
        initView();

        return mLeftView;
    }

    private void initView(){
        first_item = mLeftView.findViewById(R.id.first_item);
        second_item = mLeftView.findViewById(R.id.second_item);
        third_item = mLeftView.findViewById(R.id.third_item);
        forth_item = mLeftView.findViewById(R.id.forth_item);
        fifth_item = mLeftView.findViewById(R.id.fifth_item);

        first_item.setOnClickListener(this);
        second_item.setOnClickListener(this);
        third_item.setOnClickListener(this);
        forth_item.setOnClickListener(this);
        fifth_item.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch(id){
            case R.id.first_item:
                Toast.makeText(getActivity(),"第一个",2000).show();
                break;
        }
    }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?attr/layout_bg_normal">

    <fly.drawerandtab.widget.CustomerScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/fragment_left_items"/>

    </fly.drawerandtab.widget.CustomerScrollView>
</LinearLayout>

2. FragmentTabHost实现底部菜单

  • 自定义一个类继承FragmentTabHost:
package fly.drawerandtab.widget;

import android.content.Context;
import android.support.v4.app.FragmentTabHost;
import android.util.AttributeSet;

/**
 * Created by Fly on 2016/6/26.
 */
public class MyFragmentTabHost extends FragmentTabHost {
    private String mCurrentTag;
    private String mNoTabChangedTag;

    public MyFragmentTabHost(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onTabChanged(String tabId) {
        if(tabId.equals(mNoTabChangedTag)){
            setCurrentTabByTag(mCurrentTag);
        }else{
            super.onTabChanged(tabId);
            mCurrentTag = tabId;
        }
    }

    public void setNoTabChangedTag(String tag) {
        this.mNoTabChangedTag = tag;
    }
}
  • 放入布局文件中。(在第一部分)
  • 定义每一个Tab的内容,继承Fragment就好,这里贴上一个的代码:
package fly.drawerandtab.fragment;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import fly.drawerandtab.R;
import fly.drawerandtab.interf.OnTabReselectListener;

/**
 * Created by Fly on 2016/6/26.
 */
public class MeFragment extends Fragment implements OnTabReselectListener{
    private View mView;
    private TextView mTextView;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_me, container, false);
        mTextView = (TextView) mView.findViewById(R.id.me_txt);

        return mView;
    }


    @Override
    public void onTabReselect() {
        mTextView.setText(R.string.double_click);
    }
}
  • 存储Tab的信息:
package fly.drawerandtab.ui;

import fly.drawerandtab.R;
import fly.drawerandtab.fragment.ExploreFragment;
import fly.drawerandtab.fragment.MeFragment;
import fly.drawerandtab.fragment.NewsFragment;
import fly.drawerandtab.fragment.TweetFragment;

/**
 * Created by Fly on 2016/6/26.
 */
public enum MainTab {
    NEWS(0, R.string.main_tab_news, R.drawable.tab_icon_new, NewsFragment.class),

    TWEET(1, R.string.main_tab_tweet, R.drawable.tab_icon_tweet, TweetFragment.class),

    QUICK(2, R.string.main_tab_quick, R.drawable.tab_icon_new, null),

    EXPLORE(3, R.string.main_tab_explore, R.drawable.tab_icon_explore, ExploreFragment.class),

    ME(4, R.string.main_tab_me, R.drawable.tab_icon_me, MeFragment.class);

    private int index;
    private int resName;
    private int resIcon;
    private Class<?> clz;

    MainTab(int index, int resName, int resIcon, Class<?> clz) {
        this.index = index;
        this.resName = resName;
        this.resIcon = resIcon;
        this.clz = clz;

    }



    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getResIcon() {
        return resIcon;
    }

    public void setResIcon(int resIcon) {
        this.resIcon = resIcon;
    }

    public int getResName() {
        return resName;
    }

    public void setResName(int resName) {
        this.resName = resName;
    }

    public Class<?> getClz() {
        return clz;
    }

    public void setClz(Class<?> clz) {
        this.clz = clz;
    }
}
  • 在MainActivity中初始化自定义的FragmentTabHost:
package fly.drawerandtab.ui;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TabHost;
import android.widget.TextView;

import fly.drawerandtab.R;
import fly.drawerandtab.interf.OnTabReselectListener;
import fly.drawerandtab.widget.MyFragmentTabHost;

public class MainActivity extends AppCompatActivity implements TabHost.OnTabChangeListener, View.OnTouchListener {

    private DrawerLayout mDrawerLayout = null;
    private MyFragmentTabHost mTabHost;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);

        mTabHost = (MyFragmentTabHost) findViewById(R.id.tabhost);

        mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
//        mTabHost.setup(this.getLocalActivityManager());
        if (android.os.Build.VERSION.SDK_INT > 10) {
            mTabHost.getTabWidget().setShowDividers(0);
        }
        initTabs();

        mTabHost.setCurrentTab(0);
        mTabHost.setOnTabChangedListener(this);
    }

    private void initTabs() {
        MainTab[] tabs = MainTab.values();
        final int size = tabs.length;
        for (int i = 0; i < size; i++) {
            MainTab mainTab = tabs[i];
            TabHost.TabSpec spec = mTabHost.newTabSpec(getString(mainTab.getResName()));
            View indicator = LayoutInflater.from(getApplicationContext()).inflate(R.layout.tab_indicator, null);
            TextView title = (TextView) indicator.findViewById(R.id.tab_title);
            Drawable drawable = this.getResources().getDrawable(mainTab.getResIcon());
            title.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
            if (i == 2) {
                indicator.setVisibility(View.INVISIBLE);
                mTabHost.setNoTabChangedTag(getString(mainTab.getResName()));
            }
            title.setText(getString((mainTab.getResName())));

            spec.setIndicator(indicator);
            spec.setContent(new TabHost.TabContentFactory() {
                @Override
                public View createTabContent(String tag) {
                    return new View(MainActivity.this);
                }
            });
            mTabHost.addTab(spec, mainTab.getClz(), null);
            mTabHost.getTabWidget().getChildAt(i).setOnTouchListener(this);
        }
    }

    @Override
    public void onTabChanged(String tabId) {
        final int size = mTabHost.getTabWidget().getTabCount();
        for (int i = 0; i < size; i++) {
            View v = mTabHost.getTabWidget().getChildAt(i);
            if (i == mTabHost.getCurrentTab()) {
                v.setSelected(true);
            } else {
                v.setSelected(false);
            }
        }

        supportInvalidateOptionsMenu();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        super.onTouchEvent(event);
        boolean consumed = false;
        // use getTabHost().getCurrentTabView to decide if the current tab is
        // touched again
        if (event.getAction() == MotionEvent.ACTION_DOWN
                && v.equals(mTabHost.getCurrentTabView())) {
            // use getTabHost().getCurrentView() to get a handle to the view
            // which is displayed in the tab - and to get this views context
            Fragment currentFragment = getCurrentFragment();
            if (currentFragment != null
                    && currentFragment instanceof OnTabReselectListener) {
                OnTabReselectListener listener = (OnTabReselectListener) currentFragment;
                listener.onTabReselect();
                consumed = true;
            }
        }
        return consumed;
    }

    private Fragment getCurrentFragment() {
        return getSupportFragmentManager().findFragmentByTag(
                mTabHost.getCurrentTabTag());
    }
}

这里写了一个接口,是为了判断是否再次点了当前的tab:

package fly.drawerandtab.interf;

/**
 * Created by Fly on 2016/7/17.
 */
public interface OnTabReselectListener {
    void onTabReselect();
}

源码地址:GitHub地址
CSDN地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DrawerLayout与FragmentTabHost结合模仿oschina主界面 的相关文章

  • Android 在打开应用程序时会广播吗?

    例如 如果我想知道Youtube何时打开 是否有与之相关的广播 我当然知道我可以轮询 logcat 消息来检查活动 但我可以通过广播来做到这一点吗 因为它会少得多的耗电 此链接似乎表明这是不可能的 如何跟踪 Android 中的应用程序使用
  • Twitter 登录说明

    我想在 Android 中创建一个 Twitter 应用程序 为此 我想创建一个登录页面并登录到 Twitter 为此 我们需要消费者密钥和消费者密钥 这是什么意思 要创建此登录页面 除了 Twitter 帐户之外 我们还需要其他任何东西吗
  • 自定义选择器活动:SecurityException UID n 无权 content:// uri

    我正在构建一个选择器应用程序来替换本机 Android 共享对话框 它工作正常 除非我尝试通过长按图像 gt 共享图像从 Chrome 共享图像 我发现 Google 没有捕获异常 它崩溃了 所以我可以通过 Logcat 查看它 在 Goo
  • 带有一、二和三个按钮的 Android 警报对话框

    我不经常发出警报 但每次发出警报时 我都会花一些时间来阅读文档 https developer android com guide topics ui dialogs html并弄清楚如何去做 由于我现在不得不这样做几次 所以我将在下面写一
  • Android 如何更改 OnTouchListener 上的按钮背景

    你好 我在 xml 中有一个按钮 我正在使用OnTouchListener在我的活动中获得button按下并释放 但问题是 当我按下按钮时背景颜色没有改变 当我延长可能的活动时OnClickListener背景正在改变 任何人都可以告诉我的
  • 带操作按钮的颤动本地通知

    我在我的 flutter 项目中尝试了 flutter 本地通知插件 它在简单通知上工作正常 但我需要带有操作按钮的通知功能 请帮助我或建议我实现此功能 不幸的是 flutter local notifications 插件尚不支持操作按钮
  • 如何在android线性布局上获得阴影? [复制]

    这个问题在这里已经有答案了 可能的重复 如何在android中为View设置阴影 https stackoverflow com questions 4406524 how to set shadow to a view in androi
  • 如何在android中设置权限WRITE_SECURE_SETTINGS? [复制]

    这个问题在这里已经有答案了 我正在尝试启用 4 0 以上的辅助功能服务设置 但它显示异常 即 引起原因 java lang SecurityException 权限拒绝 写入安全设置需要 android permission WRITE S
  • Camera.open()返回NULL Android开发

    我正在按照构建相机应用程序的教程进行操作http developer android com tools device html http developer android com tools device html我对 Camera o
  • Android 应用程序中的 Eszett (ß)

    我的 res layout activity 文件中的德语 字符在我的应用程序中自动转换为 ss 即使我将语言和键盘设置为德语 它仍然不会显示 Android 中可以显示 吗 edit
  • 如何检查用户在EditText中输入自己的电话号码?

    用户将在我的 Android 应用程序的注册页面上的编辑文本中输入手机号码 如何检查用户输入的是他 她的手机号码而不是其他人的 我试过这个 TelephonyManager tMgr TelephonyManager mAppContext
  • 使用 SQLITE 按最近的纬度和经度坐标排序

    我必须获得一个 SQLite SQL 语句 以便在给定初始位置的情况下按最近的纬度和经度坐标进行排序 这是我在 sqlite 数据库中的表的例句 SELECT id name lat lng FROM items EXAMPLE RESUL
  • Android 后台服务示例,具有交互式调用方法

    我不是 Android 方面的专家 我正在寻找一个 Android 应用程序的示例 该应用程序使用一个服务 其中有真正的功能方法 或者换句话说 一个服务可以用来做什么 我们什么时候需要它 超越简单的东西服务举例 我确信您渴望获得一些工作代码
  • 有关 ListView 自定义行布局项目上的 onClick() 事件的帮助

    我有一个 ListView 其行由我格式化 每行都有 ImageView 和 TextView 的混合 我还实现了自己的适配器 并且能够通过它绘制每一行 现在 我想要这样的东西 用户单击 ImageView 不是行上的其他任何位置 但只有此
  • 如何修改 Skobbler 注释而不重新添加它

    我必须修改 SKAnnotation 的图像 注释生成器代码 private SKAnnotation getAnnotationFromView int id int minZoomLvl View view SKAnnotation a
  • 如何在android asynctask中使用inputstream作为参数?

    我正在制作一个 Android 应用程序来跟踪股票详细信息 我将通过 csv 雅虎财经 检索数据 据我所知 在android 4 0中 网络连接无法在主线程上完成 因此 我将使用 asynctask 来建立连接 但是 我在参数方面遇到了一些
  • 模块中的类无法加载

    我正在开发一个 2D Unity android 游戏 其中我最近添加了 Firebase Beta SDK 但添加后FirebaseAnalytics unitypackage我面临的错误是 无法加载模块中的类 当我删除文件夹时Fireb
  • 尝试将 SQLite DB 从数据复制到 SD 卡

    我正在使用以下代码 该代码发布在 Stack Overflow 上的某个位置 并根据我的目的进行了修改 try File sd Environment getExternalStorageDirectory File data Enviro
  • 如何在片段中实现 onBackPressed() 和意图?

    我知道 onBackPressed 是活动中的一种方法 但是 我想在片段中使用该功能 以便当按下后退按钮时 它会通过 Intent 重定向到另一个活动 有什么办法解决这个问题吗 public class News Events fragme
  • Android 材料芯片组件崩溃应用程序。无法膨胀 xml

    Tried Chip来自两个支持库的组件 com google android support design 28 0 0 rc01和材料 com google android material material 1 0 0 rc01 堆栈

随机推荐

  • 使用XMind解决问题?只需4个简单步骤!

    我们每天都在解决问题并做出决定 从我应该穿什么到学校的小问题到如何找工作或上大学等等的问题 我们面临的问题可能或大或小 或简单或复杂 无论它是什么 我们都必须解决它 解决问题和决策是商业和生活的重要技能 我们生活中非常重要的一部分是找到解决
  • UE4_积分相同排名显示问题

    找了一下ue4 rank 函数相关 没找到合适的 自己简单写了个 解决积分相同时名次要一样 之后顺位排序 中国式排名 蓝图实现 c 原理一样 1 2 3 4 5
  • 编译 QT4.6.3 出现 derefIfNotNull 未定义 解决

    使用高版本的编译工具编译QT4 6 3 出现错误 derefIfNotNull 未定义 找到 RefPtr h文件 在WFT 的 public 里面增加 两个函数的定义 void derefIfNotNull T ptr if LIKELY
  • CS从头配置电脑清单(软件篇)

    CS从头配置电脑清单 软件篇 假设你电脑丢了 重新搞了一台 怎么从头配置 迅速可以进行高效产出 假设你是Linux ubuntu系统 安装zoom 安装slack 进行其他设备的信息发送 自己给自己发 项目交流 安装截图软件 推荐flame
  • 【Java】QueryWrapper方法解释

    继承自 AbstractWrapper 自身的内部属性 entity 也用于生成 where 条件 及 LambdaQueryWrapper 可以通过 new QueryWrapper lambda 方法获取 queryWrapper lt
  • 加解密

    目录 一 加密基础知识 1 加密函数 密钥 反函数 2 加密 解密 3 对称加密 4 非对称加密 公钥私钥 二 非对称加密 1 大素数分解问题类 1 RSA 2 Rabin 3 Pollard s rho 素数分解算法 2 离散对数问题类
  • 论文笔记-深度估计(5)Unsupervised Monocular Depth Estimation with Left-Right Consistency

    ECCV2016 Unsupervised Monocular Depth Estimation with Left Right Consistency 本文采用无监督学习 没有ground truth 的方法来估计深度 基本思路是匹配好左
  • Graph Neural Network-Based Anomaly Detection in Multivariate Time Series 代码配置及解析

    可以在GPU上跑通的代码 含数据集 我已经放到了以下链接 链接 https pan baidu com s 1gM4KTbRNHzfbGEGgvEjXAw 提取码 e7wu 在服务器上跑 先创建一个虚拟环境 conda create n G
  • 算法——B树,B-树,B+树,B*树全面解析笔记

    算法 B树 B 树 B 树 B 树全面解析笔记 https www cnblogs com lianzhilei p 11250589 html http blog codinglabs org articles theory of mys
  • 【QT】混合UI设计

    虽然利用Designer和代码的设计方式都可以开发GUI 但是毫无疑问的是最有效的开发方式是利用两者进行混合开发 下面这个实验例子来自 QT5 9 C 开发指南 我做了小部分修改 最终效果是这样 图标导入 这次我们要开发的是一个有工具栏 菜
  • 哈希表——哈希表的概念,哈希表的实现(闭散列,开散列)详细解析

    作者 努力学习的少年 个人简介 双非大二 一个正在自学c 和linux操作系统 写博客是总结知识 方便复习 目标 进大厂 如果你觉得文章可以的话 麻烦你给我点个赞和关注 感谢你的关注 种一颗树最好是10年前 其次是现在 目录 哈希概念 哈希
  • 实战怎么用u盘重装系统

    当电脑系统出现故障问题无法进系统的情况下 我们可以通过制作u盘启动盘进pe系统进行修复或者重装系统解决 不过很多网友不知道怎么用u盘重装系统 今天小编就给大家分享一个简单易操作的u盘重装系统教程 具体的步骤如下 1 先在一台可用的电脑上下载
  • nodejs服务后台持续运行三种方法

    网上看到的 用了第二种方式OK的 自己备份保存下 一 利用 forever forever是一个nodejs守护进程 完全由命令行操控 forever会监控nodejs服务 并在服务挂掉后进行重启 1 安装 forever npm inst
  • 微信小程序之内嵌网页(webview)

    微信小程序提供了新的开放能力 它终于开放了在小程序中内嵌HTML页面的功能 从微信小程序基础库1 6 4开始 我们就可以在小程序内放置一个
  • 蓝桥杯大赛— —每日一题(6、走方格)

    走方格 题目描述 在平面上有一些二维的点阵 这些点的编号就像二维数组的编号一样 从上到下依次为第 1 至第 n 行 从左到右依次为第 1 至第 m 列 每一个点可以用行号和列号来表示 现在有个人站在第 1 行第 1 列 要走到第 n 行第
  • Redis可以代替MySQL作为数据库吗

    Redis可以代替MySQL作为数据库吗 当使用Redis作为数据库时 以下是一些基本的代码示例 1 连接到Redis服务器 2 存储和获取数据 3 列表操作 4 有序集合操作 6 键过期和删除 Redis作为数据库时 下面是一些更复杂的代
  • 如何基于G6进行双树流转绘制?

    1 背景 业务背景 CRM系统随着各业务条线对线索精细化分配的诉求逐渐增加 各个条线的流向规则会越来越复杂 各个条线甚至整个CRM的线索流转规则急需一种树形的可视化的图来表达 技术背景 在开发之前考虑了三种方案 原生canvas fabri
  • STM32 同个定时器 采用2个通道输入捕获

    工作中遇到 做点总结 之前看CSDN 找到一种写法 就是 把中断中的 CAPTURE VAL 的值 变成 date1 date2 去保存 但是我的写法不成功 一位大佬帮忙改成功了 总结我的写法错误之处 主函数区别 我把date1 清0 放后
  • java longlong_java Long long

    在Java中执行如下的代码 long number 26012402244 编译的时候会出现一个错误 提示 过大的整数 32322355744 如果在Eclipse中书写上面的代码 提示的是 The literal 26012402244
  • DrawerLayout与FragmentTabHost结合模仿oschina主界面

    1 DrawerLayout实现侧滑菜单 drawerlayout是官方出的侧滑菜单控件 使用起来非常方便 将它当作LinearLayout一样的布局控件 完成布局xml文件