热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android实现Tab布局的4种方式(Fragment+TabPageIndicator+ViewPager)

Android现在实现Tab类型的界面方式越来越多,今天就把常见的实现方式给大家来个总结。目前写了: 1、传统的ViewPager实现

Android现在实现Tab类型的界面方式越来越多,今天就把常见的实现方式给大家来个总结。目前写了:

1、传统的ViewPager实现

2、FragmentManager+Fragment实现

3、ViewPager+FragmentPagerAdapter实现

4、TabPageIndicator+ViewPager+FragmentPagerAdapter

1、传统的ViewPager实现

主要就是ViewPager+ViewAdapter这个还是比较常见的,就不多说了

效果图:

代码:

package com.example.mainframework02; 
 
import javautilArrayList; 
import javautilList; 
 
import androidappActivity; 
import androidosBundle; 
import androidsupportvviewPagerAdapter; 
import androidsupportvviewViewPager; 
import androidsupportvviewViewPagerOnPageChangeListener; 
import androidviewLayoutInflater; 
import androidviewView; 
import androidviewViewGroup; 
import androidwidgetImageButton; 
import androidwidgetImageView; 
import androidwidgetLinearLayout; 
 
public class TraditionalViewPagerAcvitity extends Activity 
{ 
 
  /** 
   * ViewPager 
   */ 
  private ViewPager mViewPager; 
  /** 
   * ViewPager的适配器 
   */ 
  private PagerAdapter mAdapter; 
  private List mViews; 
  private LayoutInflater mInflater; 
   
  private int currentIndex; 
 
  /** 
   * 底部四个按钮 
   */ 
  private LinearLayout mTabBtnWeixin; 
  private LinearLayout mTabBtnFrd; 
  private LinearLayout mTabBtnAddress; 
  private LinearLayout mTabBtnSettings; 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) 
  { 
    superonCreate(savedInstanceState); 
    setContentView(Rlayoutactivity_main); 
    mInflater = LayoutInflaterfrom(this); 
    mViewPager = (ViewPager) findViewById(Ridid_viewpager); 
     
    /** 
     * 初始化View 
     */ 
    initView(); 
     
    mViewPagersetAdapter(mAdapter); 
 
    mViewPagersetOnPageChangeListener(new OnPageChangeListener() 
    { 
 
      @Override 
      public void onPageSelected(int position) 
      { 
        resetTabBtn(); 
        switch (position) 
        { 
        case 0: 
          ((ImageButton) mTabBtnWeixinfindViewById(Ridbtn_tab_bottom_weixin)) 
              setImageResource(Rdrawabletab_weixin_pressed); 
          break; 
        case 1: 
          ((ImageButton) mTabBtnFrdfindViewById(Ridbtn_tab_bottom_friend)) 
              setImageResource(Rdrawabletab_find_frd_pressed); 
          break; 
        case 2: 
          ((ImageButton) mTabBtnAddressfindViewById(Ridbtn_tab_bottom_contact)) 
              setImageResource(Rdrawabletab_address_pressed); 
          break; 
        case 3: 
          ((ImageButton) mTabBtnSettingsfindViewById(Ridbtn_tab_bottom_setting)) 
              setImageResource(Rdrawabletab_settings_pressed); 
          break; 
        } 
 
        currentIndex = position; 
      } 
 
      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) 
      { 
 
      } 
 
      @Override 
      public void onPageScrollStateChanged(int arg0) 
      { 
      } 
    }); 
 
  } 
 
  protected void resetTabBtn() 
  { 
    ((ImageButton) mTabBtnWeixinfindViewById(Ridbtn_tab_bottom_weixin)) 
        setImageResource(Rdrawabletab_weixin_normal); 
    ((ImageButton) mTabBtnFrdfindViewById(Ridbtn_tab_bottom_friend)) 
        setImageResource(Rdrawabletab_find_frd_normal); 
    ((ImageButton) mTabBtnAddressfindViewById(Ridbtn_tab_bottom_contact)) 
        setImageResource(Rdrawabletab_address_normal); 
    ((ImageButton) mTabBtnSettingsfindViewById(Ridbtn_tab_bottom_setting)) 
        setImageResource(Rdrawabletab_settings_normal); 
  } 
 
  private void initView() 
  { 
 
    mTabBtnWeixin = (LinearLayout) findViewById(Ridid_tab_bottom_weixin); 
    mTabBtnFrd = (LinearLayout) findViewById(Ridid_tab_bottom_friend); 
    mTabBtnAddress = (LinearLayout) findViewById(Ridid_tab_bottom_contact); 
    mTabBtnSettings = (LinearLayout) findViewById(Ridid_tab_bottom_setting); 
 
    mViews = new ArrayList(); 
    View first = mInflaterinflate(Rlayoutmain_tab_01, null); 
    View secOnd= mInflaterinflate(Rlayoutmain_tab_02, null); 
    View third = mInflaterinflate(Rlayoutmain_tab_03, null); 
    View fourth = mInflaterinflate(Rlayoutmain_tab_04, null); 
    mViewsadd(first); 
    mViewsadd(second); 
    mViewsadd(third); 
    mViewsadd(fourth); 
 
    mAdapter = new PagerAdapter() 
    { 
      @Override 
      public void destroyItem(ViewGroup container, int position, Object object) 
      { 
        containerremoveView(mViewsget(position)); 
      } 
 
      @Override 
      public Object instantiateItem(ViewGroup container, int position) 
      { 
        View view = mViewsget(position); 
        containeraddView(view); 
        return view; 
      } 
 
      @Override 
      public boolean isViewFromObject(View arg0, Object arg1) 
      { 
        return arg0 == arg1; 
      } 
 
      @Override 
      public int getCount() 
      { 
        return mViewssize(); 
      } 
    }; 
  } 
 
} 

评价:所有的代码都集中在一个Activity中,显得代码比较乱。

2、FragmentManager+Fragment实现

主要利用了Fragment在主内容界面对Fragment的add,hide等事务操作。

效果图:

代码:

主Activity

package com.example.mainframework02.fragment; 
 
import androidannotationSuppressLint; 
import androidappActivity; 
import androidappFragmentManager; 
import androidappFragmentTransaction; 
import androidosBundle; 
import androidviewView; 
import androidviewViewOnClickListener; 
import androidwidgetImageButton; 
import androidwidgetLinearLayout; 
 
import comexamplemainframeworkR; 
 
public class FragmentMainActivity extends Activity implements OnClickListener 
{ 
  private MainTab02 mTab02; 
  private MainTab01 mTab01; 
  private MainTab03 mTab03; 
  private MainTab04 mTab04; 
 
  /** 
   * 底部四个按钮 
   */ 
  private LinearLayout mTabBtnWeixin; 
  private LinearLayout mTabBtnFrd; 
  private LinearLayout mTabBtnAddress; 
  private LinearLayout mTabBtnSettings; 
  /** 
   * 用于对Fragment进行管理 
   */ 
  private FragmentManager fragmentManager; 
 
  @SuppressLint("NewApi") 
  @Override 
  protected void onCreate(Bundle savedInstanceState) 
  { 
    superonCreate(savedInstanceState); 
    setContentView(Rlayoutfragment_main); 
    initViews(); 
    fragmentManager = getFragmentManager(); 
    setTabSelection(0); 
  } 
 
   
 
  private void initViews() 
  { 
 
    mTabBtnWeixin = (LinearLayout) findViewById(Ridid_tab_bottom_weixin); 
    mTabBtnFrd = (LinearLayout) findViewById(Ridid_tab_bottom_friend); 
    mTabBtnAddress = (LinearLayout) findViewById(Ridid_tab_bottom_contact); 
    mTabBtnSettings = (LinearLayout) findViewById(Ridid_tab_bottom_setting); 
 
    mTabBtnWeixinsetOnClickListener(this); 
    mTabBtnFrdsetOnClickListener(this); 
    mTabBtnAddresssetOnClickListener(this); 
    mTabBtnSettingssetOnClickListener(this); 
  } 
 
  @Override 
  public void onClick(View v) 
  { 
    switch (vgetId()) 
    { 
    case Ridid_tab_bottom_weixin: 
      setTabSelection(0); 
      break; 
    case Ridid_tab_bottom_friend: 
      setTabSelection(1); 
      break; 
    case Ridid_tab_bottom_contact: 
      setTabSelection(2); 
      break; 
    case Ridid_tab_bottom_setting: 
      setTabSelection(3); 
      break; 
 
    default: 
      break; 
    } 
  } 
 
  /** 
   * 根据传入的index参数来设置选中的tab页。 
   * 
   */ 
  @SuppressLint("NewApi") 
  private void setTabSelection(int index) 
  { 
    // 重置按钮 
    resetBtn(); 
    // 开启一个Fragment事务 
    FragmentTransaction transaction = fragmentManagerbeginTransaction(); 
    // 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况 
    hideFragments(transaction); 
    switch (index) 
    { 
    case 0: 
      // 当点击了消息tab时,改变控件的图片和文字颜色 
      ((ImageButton) mTabBtnWeixinfindViewById(Ridbtn_tab_bottom_weixin)) 
          setImageResource(Rdrawabletab_weixin_pressed); 
      if (mTab01 == null) 
      { 
        // 如果MessageFragment为空,则创建一个并添加到界面上 
        mTab01 = new MainTab01(); 
        transactionadd(Ridid_content, mTab01); 
      } else 
      { 
        // 如果MessageFragment不为空,则直接将它显示出来 
        transactionshow(mTab01); 
      } 
      break; 
    case 1: 
      // 当点击了消息tab时,改变控件的图片和文字颜色 
      ((ImageButton) mTabBtnFrdfindViewById(Ridbtn_tab_bottom_friend)) 
          setImageResource(Rdrawabletab_find_frd_pressed); 
      if (mTab02 == null) 
      { 
        // 如果MessageFragment为空,则创建一个并添加到界面上 
        mTab02 = new MainTab02(); 
        transactionadd(Ridid_content, mTab02); 
      } else 
      { 
        // 如果MessageFragment不为空,则直接将它显示出来 
        transactionshow(mTab02); 
      } 
      break; 
    case 2: 
      // 当点击了动态tab时,改变控件的图片和文字颜色 
      ((ImageButton) mTabBtnAddressfindViewById(Ridbtn_tab_bottom_contact)) 
          setImageResource(Rdrawabletab_address_pressed); 
      if (mTab03 == null) 
      { 
        // 如果NewsFragment为空,则创建一个并添加到界面上 
        mTab03 = new MainTab03(); 
        transactionadd(Ridid_content, mTab03); 
      } else 
      { 
        // 如果NewsFragment不为空,则直接将它显示出来 
        transactionshow(mTab03); 
      } 
      break; 
    case 3: 
      // 当点击了设置tab时,改变控件的图片和文字颜色 
      ((ImageButton) mTabBtnSettingsfindViewById(Ridbtn_tab_bottom_setting)) 
          setImageResource(Rdrawabletab_settings_pressed); 
      if (mTab04 == null) 
      { 
        // 如果SettingFragment为空,则创建一个并添加到界面上 
        mTab04 = new MainTab04(); 
        transactionadd(Ridid_content, mTab04); 
      } else 
      { 
        // 如果SettingFragment不为空,则直接将它显示出来 
        transactionshow(mTab04); 
      } 
      break; 
    } 
    transactioncommit(); 
  } 
 
  /** 
   * 清除掉所有的选中状态。 
   */ 
  private void resetBtn() 
  { 
    ((ImageButton) mTabBtnWeixinfindViewById(Ridbtn_tab_bottom_weixin)) 
        setImageResource(Rdrawabletab_weixin_normal); 
    ((ImageButton) mTabBtnFrdfindViewById(Ridbtn_tab_bottom_friend)) 
        setImageResource(Rdrawabletab_find_frd_normal); 
    ((ImageButton) mTabBtnAddressfindViewById(Ridbtn_tab_bottom_contact)) 
        setImageResource(Rdrawabletab_address_normal); 
    ((ImageButton) mTabBtnSettingsfindViewById(Ridbtn_tab_bottom_setting)) 
        setImageResource(Rdrawabletab_settings_normal); 
  } 
 
  /** 
   * 将所有的Fragment都置为隐藏状态。 
   * 
   * @param transaction 
   *      用于对Fragment执行操作的事务 
   */ 
  @SuppressLint("NewApi") 
  private void hideFragments(FragmentTransaction transaction) 
  { 
    if (mTab01 != null) 
    { 
      transactionhide(mTab01); 
    } 
    if (mTab02 != null) 
    { 
      transactionhide(mTab02); 
    } 
    if (mTab03 != null) 
    { 
      transactionhide(mTab03); 
    } 
    if (mTab04 != null) 
    { 
      transactionhide(mTab04); 
    } 
     
  } 
 
} 

各个TabFragment,一共四个TabFragment,下面贴出两个,基本都一样。

package com.example.mainframework02.fragment; 
 
import androidannotationSuppressLint; 
import androidappFragment; 
import androidosBundle; 
import androidviewLayoutInflater; 
import androidviewView; 
import androidviewViewGroup; 
 
@SuppressLint("NewApi") 
public class MainTab01 extends Fragment 
{ 
 
  @Override 
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
  { 
    return inflaterinflate(comexamplemainframeworkRlayoutmain_tab_01, container, false); 
 
  } 
 
} 


package com.example.mainframework02.fragment; 
 
import androidannotationSuppressLint; 
import androidappFragment; 
import androidosBundle; 
import androidviewLayoutInflater; 
import androidviewView; 
import androidviewViewGroup; 
 
import comexamplemainframeworkR; 
 
@SuppressLint("NewApi") 
public class MainTab02 extends Fragment 
{ 
 
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
  { 
    return inflaterinflate(Rlayoutmain_tab_02, container, false); 
 
  } 
 
} 

评价:每个Fragment中的控件的处理,都是独立到各自的类中,相对来说主Activity简化了不少,可惜没有左右滑动的效果了。

3、ViewPager+Fragment实现

主要通过ViewPager和FragmentPagerAdapter一起来实现。

效果图:

代码:

主Activity

package com.example.mainframework03; 
 
import javautilArrayList; 
import javautilList; 
 
import androidosBundle; 
import androidsupportvappFragment; 
import androidsupportvappFragmentActivity; 
import androidsupportvappFragmentPagerAdapter; 
import androidsupportvviewViewPager; 
import androidsupportvviewViewPagerOnPageChangeListener; 
import androidwidgetImageButton; 
import androidwidgetLinearLayout; 
 
public class MainActivity extends FragmentActivity 
{ 
 
  private ViewPager mViewPager; 
  private FragmentPagerAdapter mAdapter; 
  private List mFragments = new ArrayList(); 
   
   
  /** 
   * 底部四个按钮 
   */ 
  private LinearLayout mTabBtnWeixin; 
  private LinearLayout mTabBtnFrd; 
  private LinearLayout mTabBtnAddress; 
  private LinearLayout mTabBtnSettings; 
 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) 
  { 
    superonCreate(savedInstanceState); 
    setContentView(Rlayoutactivity_main); 
    mViewPager = (ViewPager) findViewById(Ridid_viewpager); 
 
     
    initView(); 
     
     
 
    mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) 
    { 
 
      @Override 
      public int getCount() 
      { 
        return mFragmentssize(); 
      } 
 
      @Override 
      public Fragment getItem(int arg0) 
      { 
        return mFragmentsget(arg0); 
      } 
    }; 
     
    mViewPagersetAdapter(mAdapter); 
     
     
    mViewPagersetOnPageChangeListener(new OnPageChangeListener() 
    { 
 
      private int currentIndex; 
 
      @Override 
      public void onPageSelected(int position) 
      { 
        resetTabBtn(); 
        switch (position) 
        { 
        case 0: 
          ((ImageButton) mTabBtnWeixinfindViewById(Ridbtn_tab_bottom_weixin)) 
              setImageResource(Rdrawabletab_weixin_pressed); 
          break; 
        case 1: 
          ((ImageButton) mTabBtnFrdfindViewById(Ridbtn_tab_bottom_friend)) 
              setImageResource(Rdrawabletab_find_frd_pressed); 
          break; 
        case 2: 
          ((ImageButton) mTabBtnAddressfindViewById(Ridbtn_tab_bottom_contact)) 
              setImageResource(Rdrawabletab_address_pressed); 
          break; 
        case 3: 
          ((ImageButton) mTabBtnSettingsfindViewById(Ridbtn_tab_bottom_setting)) 
              setImageResource(Rdrawabletab_settings_pressed); 
          break; 
        } 
 
        currentIndex = position; 
      } 
 
      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) 
      { 
 
      } 
 
      @Override 
      public void onPageScrollStateChanged(int arg0) 
      { 
      } 
    }); 
 
  } 
   
  protected void resetTabBtn() 
  { 
    ((ImageButton) mTabBtnWeixinfindViewById(Ridbtn_tab_bottom_weixin)) 
        setImageResource(Rdrawabletab_weixin_normal); 
    ((ImageButton) mTabBtnFrdfindViewById(Ridbtn_tab_bottom_friend)) 
        setImageResource(Rdrawabletab_find_frd_normal); 
    ((ImageButton) mTabBtnAddressfindViewById(Ridbtn_tab_bottom_contact)) 
        setImageResource(Rdrawabletab_address_normal); 
    ((ImageButton) mTabBtnSettingsfindViewById(Ridbtn_tab_bottom_setting)) 
        setImageResource(Rdrawabletab_settings_normal); 
  } 
 
  private void initView() 
  { 
 
    mTabBtnWeixin = (LinearLayout) findViewById(Ridid_tab_bottom_weixin); 
    mTabBtnFrd = (LinearLayout) findViewById(Ridid_tab_bottom_friend); 
    mTabBtnAddress = (LinearLayout) findViewById(Ridid_tab_bottom_contact); 
    mTabBtnSettings = (LinearLayout) findViewById(Ridid_tab_bottom_setting); 
 
    MainTab01 tab01 = new MainTab01(); 
    MainTab02 tab02 = new MainTab02(); 
    MainTab03 tab03 = new MainTab03(); 
    MainTab04 tab04 = new MainTab04(); 
    mFragmentsadd(tab01); 
    mFragmentsadd(tab02); 
    mFragmentsadd(tab03); 
    mFragmentsadd(tab04); 
  } 
} 

还有4个TabFragment,下面贴一个,四个基本一样

package com.example.mainframework03; 
 
import androidosBundle; 
import androidsupportvappFragment; 
import androidviewLayoutInflater; 
import androidviewView; 
import androidviewViewGroup; 
 
public class MainTab01 extends Fragment 
{ 
 
  @Override 
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
  { 
    return inflaterinflate(Rlayoutmain_tab_01, container, false); 
   
  } 
 
} 

评价:实现效果和第一种效果一模一样,每个Fragment独自处理自己内部的逻辑,代码整洁很多,并且支持左右滑动。感觉是第一种和第二种的结合版本。

4、TabPageIndicator+ViewPager+FragmentPagerAdapter

实现方式和3是一致的,但是使用了TabPageIndicator作为tab的指示器,效果还是不错的,这个之前写过,就不再贴代码了。

效果图:

好了,就总结了这么多,肯定还有很多别的实现方式,大家可以留言,有时间会继续完善这篇总结的。

第一种和第二种的源码:demo下载

第三种方式的源码:demo下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 在 HihoCoder 1505 中,题目要求从给定的 n 个数中选取两对数,使这两对数的和相等。如果直接对所有可能的组合进行遍历,时间复杂度将达到 O(n^4),因此需要考虑优化选择过程。通过使用哈希表或其他高效的数据结构,可以显著降低时间复杂度,从而提高算法的效率。具体实现中,可以通过预处理和存储中间结果来减少重复计算,进一步提升性能。 ... [详细]
  • 在探讨如何高效处理大规模数据报表的分页展示之前,首先需要明确导致报表加载缓慢的主要原因。通常情况下,这主要是由于两个方面:一是查询条件过于宽泛,使得数据库返回的结果集包含数百万甚至更多的记录;二是前端渲染性能不足,无法高效处理大量数据。为了优化这一过程,可以从以下几个方面入手:优化查询条件,减少不必要的数据返回;采用分页查询技术,每次仅加载所需的数据;利用缓存机制,减少对数据库的频繁访问;提升前端渲染效率,使用虚拟滚动等技术提高用户体验。 ... [详细]
  • 新年伊始,正是学习的最佳时机。本文全面解析了CK1957-Zookeeper的核心概念与实践技巧,旨在帮助初学者快速掌握这一深度学习工具。通过详细的理论讲解和实际操作示例,读者可以更好地理解Zookeeper的工作原理及其在分布式系统中的应用。无论是新手还是有一定基础的学习者,都能从中受益匪浅。 ... [详细]
  • 探究Oracle数据库字符集编码的详细方法与实践
    本文深入探讨了Oracle数据库字符集编码的详细方法与实践。首先,通过执行 `SELECT USERENV('language') FROM DUAL;` 查询服务端字符集编码。其次,通过在注册表中搜索 `NLS_LANG` 参数来查看客户端字符集编码。此外,文章还介绍了如何在不同场景下正确配置和转换字符集,以确保数据的一致性和完整性。 ... [详细]
  • 本文深入探讨了在Android应用开发中常见的相机连接故障问题,特别是在RK3288平台和Android 6.0系统上。通过分析具体案例,本文提供了详细的解决方案和应对策略,旨在帮助开发者有效解决相机连接问题,提升应用的稳定性和用户体验。 ... [详细]
  • 如何利用Python脚本实现钉钉自动化考勤打卡
    本文详细探讨了利用Python脚本实现钉钉自动化考勤打卡的方法。通过具体实例操作,解决了很多用户在实际应用中遇到的难题,帮助读者高效掌握这一实用技能。 ... [详细]
  • 摩托罗拉Razr V3焕新归来:全球首款翻盖式折叠屏智能手机重磅发布
    曾经风靡一时的摩托罗拉Razr V3如今以全新面貌回归,成为全球首款翻盖式折叠屏智能手机。这款经典机型自2004年首次推出,迅速成为市场宠儿,全球销量突破1.3亿部,奠定了其在手机史上的传奇地位。此次焕新发布的Razr V3不仅继承了原版的精致设计,还融入了最新的折叠屏技术,为用户带来前所未有的使用体验。 ... [详细]
  • Eclipse 错误解决:找不到指定的 APK 文件,项目名称未正确配置
    摘要:此问题可能是因为当前项目被错误地配置为库项目。解决方法如下:首先,打开项目属性(Project > Properties),在左侧列表中选择“Android”选项卡,取消选中“Is Library”复选框,然后点击“Apply”并重新构建项目。如果问题仍然存在,建议检查项目的构建路径和依赖关系,确保所有配置正确无误。 ... [详细]
  • 本文探讨了在Android应用中实现动态滚动文本显示控件的优化方法。通过详细分析焦点管理机制,特别是通过设置返回值为`true`来确保焦点不会被其他控件抢占,从而提升滚动文本的流畅性和用户体验。具体实现中,对`MarqueeText.java`进行了代码层面的优化,增强了控件的稳定性和兼容性。 ... [详细]
  • 在执行 Vim/VM 命令时遇到错误提示:检测到名为
    在使用 Docker 时,通过 Vim 编辑 Dockerfile 文件时遇到了错误提示:“检测到名为 .dockerfile.swp 的交换文件”。这一问题通常是因为上次编辑该文件时意外中断,导致系统生成了临时的交换文件。为了解决这个问题,可以手动删除该交换文件或使用 Vim 的恢复功能来恢复未保存的更改。 ... [详细]
  • Python学习:环境配置与安装指南
    Python作为一种跨平台的编程语言,适用于Windows、Linux和macOS等多种操作系统。为了确保本地已成功安装Python,用户可以通过终端或命令行界面输入`python`或`python3`命令进行验证。此外,建议使用虚拟环境管理工具如`venv`或`conda`,以便更好地隔离不同项目依赖,提高开发效率。 ... [详细]
  • 在 Android 开发中,通过合理利用系统通知服务,可以显著提升应用的用户交互体验。针对 Android 8.0 及以上版本,开发者需首先创建并注册通知渠道。本文将详细介绍如何在应用中实现这一功能,包括初始化通知管理器、创建通知渠道以及发送通知的具体步骤,帮助开发者更好地理解和应用这些技术细节。 ... [详细]
  • 斐波那契数在组合数学中的应用与探索
    斐波那契数列作为数学领域中一个广为人知的数列,不仅拥有丰富的数学性质,还与自然界的诸多现象紧密相连。本文将深入探讨这一数列背后的奥秘,揭示其在组合数学中的广泛应用,并通过具体问题的引入,展示斐波那契数列在解决复杂组合问题时的独特优势。 ... [详细]
  • Jenkins学习精华:自动化构建与持续集成入门指南
    本文综合了网络资源及同事分享的PPT内容,详细介绍了Jenkins在自动化构建与持续集成中的应用。首先涵盖了Jenkins的安装与配置流程,接着阐述了如何根据项目需求设定自动化编译任务,包括确定开发环境、选择合适的编译工具以及实现代码的自动更新等关键步骤。特别强调了在SVN环境中通过命令行实现代码自动拉取的最佳实践。 ... [详细]
  • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
author-avatar
皇家突然回家_390
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有