开源项目: FlycoTabLayout

android 底部标签栏CommonTabLayout搭建项目底部菜单(带消息提醒) import android.util.AttributeSet; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.animation.OvershootInterpolator; import android.wid 阅读详情

开源项目效果

调用实例

必练基本功

Android studio 项目导入依赖compile路径

dependencies{
    compile 'com.android.support:support-v4:23.1.1'
    compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.0.2@aar'
}

FlycoTabLayout是一个Android TabLayout库,目前有3个TabLayout

 /** 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 */
    public void setViewPager(ViewPager vp, String[] titles)

    /** 关联ViewPager,用于连适配器都不想自己实例化的情况 */
    public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList<Fragment> fragments) 
  • CommonTabLayout:不同于SlidingTabLayout对ViewPager依赖,它是一个不依赖ViewPager可以与其他控件自由搭配使用的TabLayout.

    • 支持多种Indicator显示器,以及Indicator动画
    • 支持未读消息显示
    • 支持Icon以及Icon位置
    • 新增方法
/** 关联数据支持同时切换fragments */
    public void setTabData(ArrayList<CustomTabEntity> tabEntitys, FragmentManager fm, int containerViewId, ArrayList<Fragment> fragments)
  • SegmentTabLayout:仿照QQ消息列表头部tab切换的控件

自定义属性表

tl_indicator_color          color       设置显示器颜色
tl_indicator_height         dimension   设置显示器高度
tl_indicator_width          dimension   设置显示器固定宽度
tl_indicator_margin_left    dimension   设置显示器margin,当indicator_width大于0,无效
tl_indicator_margin_top     dimension   设置显示器margin,当indicator_width大于0,无效
tl_indicator_margin_right   dimension   设置显示器margin,当indicator_width大于0,无效
tl_indicator_margin_bottom  dimension   设置显示器margin,当indicator_width大于0,无效
tl_indicator_corner_radius  dimension   设置显示器圆角弧度
tl_indicator_gravity        enum        设置显示器上方(TOP)还是下方(BOTTOM),只对常规显示器有用
tl_indicator_style          enum        设置显示器为常规(NORMAL)或三角形(TRIANGLE)或背景色块(BLOCK)
tl_underline_color          color       设置下划线颜色
tl_underline_height         dimension   设置下划线高度
tl_underline_gravity        enum        设置下划线上方(TOP)还是下方(BOTTOM)
tl_divider_color            color       设置分割线颜色
tl_divider_width            dimension   设置分割线宽度
tl_divider_padding          dimension   设置分割线的paddingTop和paddingBottom
tl_tab_padding              dimension   设置tab的paddingLeft和paddingRight
tl_tab_space_equal          boolean     设置tab大小等分
tl_tab_width                dimension   设置tab固定大小
tl_textsize                 dimension   设置字体大小
tl_textSelectColor          color       设置字体选中颜色
tl_textUnselectColor        color       设置字体未选中颜色
tl_textBold                 boolean     设置字体加粗
tl_iconWidth                dimension   设置icon宽度(仅支持CommonTabLayout)
tl_iconHeight               dimension   设置icon高度(仅支持CommonTabLayout)
tl_iconVisible              boolean     设置icon是否可见(仅支持CommonTabLayout)
tl_iconGravity              enum        设置icon显示位置,对应Gravity中常量值,左上右下(仅支持CommonTabLayout)
tl_iconMargin               dimension   设置icon与文字间距(仅支持CommonTabLayout)
tl_indicator_anim_enable    boolean     设置显示器支持动画(only for CommonTabLayout)
tl_indicator_anim_duration  integer     设置显示器动画时间(only for CommonTabLayout)
tl_indicator_bounce_enable  boolean     设置显示器支持动画回弹效果(only for CommonTabLayout)
tl_indicator_width_equal_title  boolean 设置显示器与标题一样长(only for SlidingTabLayout)

该库依赖于动画兼容库NineOldAndroids和FlycoRoundView,稍后在源码分析里简单了解一下FlycoRoundView。

SlidingTabLayout调用

SlidingTabLayout自定义属性支持下划线设置,控制下划线显示方向宽高,可以让线宽=文字宽度,也可以固定比例宽度,可以设置未读消息的小红点,也可以设置未读消息数量,当前这一切的前提都是基于ViewPager来实现,都需要绑定ViewPager,通过多种绑定方法

 /**关联ViewPager,Adapter重写了getPageTitle方法*/
 tabLayout.setViewPager(vp);

 /**关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况*/
 tabLayout.setViewPager(vp, mTitles);

 /**关联ViewPager,用于连适配器都不想自己实例化的情况,内部帮助实例化了一个InnerPagerAdapter*/
 tabLayout.setViewPager(vp, mTitles, this, mFragments);

下面我们来看看tabLayout提供几个对我们比较有用的方法

/**显示指定位置未读红点*/
tabLayout.showDot(4);
/**隐藏指定位置未读红点或消息*/
tabLayout.hideMsg(5);
/**showMsg(int position, int num):position位置,num小于等于0显示红点,num大于0显示数字,作用:显示未读消息,如果消息数量>99,显示效果99+*/
tabLayout.showMsg(3, 5);
/**  setMsgMargin(int position, float leftPadding, float bottomPadding)设置未读消息偏移,原点为文字的右上角.当控件高度固定,消息提示位置易控制,显示效果佳 */
tabLayout.setMsgMargin(3, 0, 10);

/**设置未读消息消息的背景*/
 MsgView msgView = tabLayout.getMsgView(3);
 if (msgView != null) {
     msgView.setBackgroundColor(Color.parseColor("#6D8FB0"));
  }
//...................略...........

自定义的属性那么多,对应的set方法自然也不少,不过对照上面自定义属性xml引用就好,一般情况下哪些方法都用不到了。

CommonTabLayout调用

SlidingTabLayout对应的方法在这里都适用不再重复,CommonTabLayout最重要的就是setTabData(ArrayList tabEntitys)方法,使得CommonTabLayout不再依赖于ViewPager完成初始化,实现底部导航或者头部导航效果,让我们告别RadioButton+ViewPager的时代,CustomTabEntity的命名有点问题哈,命名是一个接口非要定义Entity结尾,TabEntity实现该接口,修改构造方法,初始化内部参数,下面是一个配合CommonTabLayout+ViewPager的导航实例


        mFragmentList = addFragmentList(R.id.home_frameLayout, fragmentClasses);

        for (int i = 0; i < titles.length; i++) {
            mTabEntities.add(new TabEntity(titles[i], checkeds[i], normals[i]));
        }

        commonTabLayout.setTabData(mTabEntities);
        commonTabLayout.setOnTabSelectListener(new OnTabSelectListener() {
            @Override
            public void onTabSelect(int position) {

                if (position == 1) {
                    topBarBuilder.configSearchStyle(titles[position], R.drawable.ic_action_search);
                } else {
                    topBarBuilder.configTitle(titles[position]);
                }

                showFragment(R.id.home_frameLayout, position, mFragmentList);
                onLoggerD("initial callback ,show fragment with position " + position + ";FragmentName:" + mFragmentList.get(position).toString());
            }

            @Override
            public void onTabReselect(int position) {
                //TODO 重选
            }
        });
SegmentTabLayout调用

SegmentTabLayout实现效果就像qq消息列表顶部的切换效果,统一支持setTabData(mTitles)不过这里传入标题数组,tabLayout配合ViewPager切换调用tabLayout提供的方法setCurrentTab,SegmentTabLayout提供的 setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList fragments)方法在我们frameLayout+fragment布局切换Fragment比较实用的

源码分析

FlycoRoundView源码分析

粗略看过这个库的自定义属性文件,明悟了件事:自定义属性的自动提示如下(以前我自定义属性都放在declare-styleable直接定义的)

下面是这些自定义属性的具体含义(attrs里面有具体说明)


<!-- 以下是重用attr的正确姿势,一切为了在布局中可以自动提示-->
    <!-- 圆角矩形背景色 -->
    <attr name="rv_backgroundColor" format="color"/>
    <!-- 圆角矩形背景色press -->
    <attr name="rv_backgroundPressColor" format="color"/>
    <!-- 圆角弧度,单位dp-->
    <attr name="rv_cornerRadius" format="dimension"/>
    <!-- 圆角弧度,单位dp-->
    <attr name="rv_strokeWidth" format="dimension"/>
    <!-- 圆角边框颜色-->
    <attr name="rv_strokeColor" format="color"/>
    <!-- 圆角边框颜色press -->
    <attr name="rv_strokePressColor" format="color"/>
    <!-- 文字颜色press-->
    <attr name="rv_textPressColor" format="color"/>
    <!-- 圆角弧度是高度一半-->
    <attr name="rv_isRadiusHalfHeight" format="boolean"/>
    <!-- 圆角矩形宽高相等,取较宽高中大值-->
    <attr name="rv_isWidthHeightEqual" format="boolean"/>
    <!-- 圆角弧度,单位dp,TopLeft-->
    <attr name="rv_cornerRadius_TL" format="dimension"/>
    <!-- 圆角弧度,单位dp,TopRight-->
    <attr name="rv_cornerRadius_TR" format="dimension"/>
    <!-- 圆角弧度,单位dp,BottomLeft-->
    <attr name="rv_cornerRadius_BL" format="dimension"/>
    <!-- 圆角弧度,单位dp,BottomRight-->
    <attr name="rv_cornerRadius_BR" format="dimension"/>
    <!-- 是否有Ripple效果,api21+有效-->
    <attr name="rv_isRippleEnable" format="boolean"/>

    <declare-styleable name="RoundTextView">
        <attr name="rv_backgroundColor"/>
        <attr name="rv_backgroundPressColor"/>
        <attr name="rv_cornerRadius"/>
        <attr name="rv_strokeWidth"/>
        <attr name="rv_strokeColor"/>
        <attr name="rv_strokePressColor"/>
        <attr name="rv_textPressColor"/>
        <attr name="rv_isRadiusHalfHeight"/>
        <attr name="rv_isWidthHeightEqual"/>
        <attr name="rv_cornerRadius_TL"/>
        <attr name="rv_cornerRadius_TR"/>
        <attr name="rv_cornerRadius_BL"/>
        <attr name="rv_cornerRadius_BR"/>
        <attr name="rv_isRippleEnable"/>
    </declare-styleable>

Round系列的View控件自定义 RoundTextView 、RoundFrameLayout 、RoundLinearLayout RoundRelativeLayout,这几个控件内部源码实现并不复杂,可以说简单之极,构造函数通过RoundViewDelegate代理解析自定义属性,其次就是onMeasure和onLayout的测量相关的,ToggleButton源码分析一篇有提到这里使用EXACTLY

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (delegate.isWidthHeightEqual() && getWidth() > 0 && getHeight() > 0) {
            int max = Math.max(getWidth(), getHeight());
            int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY);
            super.onMeasure(measureSpec, measureSpec);
            return;
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (delegate.isRadiusHalfHeight()) { //如果弧度是高度的一半,直接设置radio为高度一半,否则调用
            delegate.setCornerRadius(getHeight() / 2);
        }else {
            delegate.setBgSelector();// Ripple效果兼容21+,Ripple效果的实现有多重,这里使用的RippleDrawable,具体使用方法请参考api,这里不是本篇重点
        }
    }

setBgSelector 方法使用到了GradientDrawable、StateListDrawable,没了解过的可以参考Drawable系列这篇博客有相应的简单介绍,RoundViewDelegate提供了这些自定义属性的set get方法,我们代码调用通过自定义控件getDelegate获取构造函数初始化的实例进行设置和获取对应属性。

FlycoTabLayout Lib库源码分析

MsgView仿照FlycoRoundView库编写的一个自定义控件,主要用于未读消息的展示,大同小异的代码就此略过。

SlidingTabLayout自定义控件千篇一律的自定义属性飘过,来到必经之路setViewPager,发现新大陆notifyDataSetChanged()调用,通过dapter的getPageTitle方法获取标题,并inflate添加一个布局到HorizontalScrollView的子View LinearLayout,并绑定Tab想的监听回调。

 /** 更新数据 */
 public void notifyDataSetChanged() {
        mTabsContainer.removeAllViews();
        this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.length;
        View tabView;
        for (int i = 0; i < mTabCount; i++) {
            if (mViewPager.getAdapter() instanceof CustomTabProvider) {
                tabView = ((CustomTabProvider) mViewPager.getAdapter()).getCustomTabView(this, i);
            } else {
                tabView = View.inflate(mContext, R.layout.layout_tab, null);
            }

            CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(i) : mTitles[i];
            addTab(i, pageTitle.toString(), tabView);
        }

        updateTabStyles();
    }

/** 创建并添加tab */
private void addTab(final int position, String title, View tabView) {
        TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
        if (tv_tab_title != null) {
            if (title != null) tv_tab_title.setText(title);
        }

        tabView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mViewPager.getCurrentItem() != position) {
                    mViewPager.setCurrentItem(position);
                    if (mListener != null) {
                        mListener.onTabSelect(position);
                    }
                } else {
                    if (mListener != null) {
                        mListener.onTabReselect(position);
                    }
                }
            }
        });

        /** 每一个Tab的布局参数 */
        LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ?
                new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) :
                new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        if (mTabWidth > 0) {
            lp_tab = new LinearLayout.LayoutParams((int) mTabWidth, LayoutParams.MATCH_PARENT);
        }

        mTabsContainer.addView(tabView, position, lp_tab);
    }

calcIndicatorRect方法根据不同的属性计算出Rect范围以便以绘制,具体绘制方法参考Canvas API,这里提一点下面这个方法非常有必要,如果在自定义控件的构造函数或者其他绘制相关地方使用系统依赖的代码,会导致可视化编辑器无法报错并提示:Use View.isInEditMode() in your custom views to skip code when shown in Eclipseis,加上了isInEditMode的判断就不会再报错了。

 if (isInEditMode() || mTabCount <= 0) {
            return;
        }

对于代码设置自定义的属性值,会调用下面这两个方法 invalidate()和 updateTabStyles();涉及到了绘制的则调用invalidate,可以直接修改的则调用updateTabStyles(个人感觉不太友好,比如代码设置一个属性值,就需要遍历所有view,同时重新调用属性赋值,关键只修改了其中一个属性!!)

  private void updateTabStyles() {
        for (int i = 0; i < mTabCount; i++) {
            View v = mTabsContainer.getChildAt(i);
//            v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom());
            TextView tv_tab_title = (TextView) v.findViewById(R.id.tv_tab_title);
            if (tv_tab_title != null) {
                tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor);
                tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize);
                tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0);
                if (mTextAllCaps) {
                    tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase());
                }

                if (mTextBold) {
                    tv_tab_title.getPaint().setFakeBoldText(mTextBold);
                }
            }
        }
    }

setMsg 、setDot方法在调用示例有提到用法,这里的show hide状态如何保存的呢?这里有用到和AbsListView内部状态保持一样的方法:SparseArray来保存对应位置的状态

    /**
     * 显示未读消息
     *
     * @param position 显示tab位置
     * @param num      num小于等于0显示红点,num大于0显示数字
     */
    public void showMsg(int position, int num) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }

        View tabView = mTabsContainer.getChildAt(position);
        MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
        if (tipView != null) {
            UnreadMsgUtils.show(tipView, num);

            if (mInitSetMap.get(position) != null && mInitSetMap.get(position)) {
                return;
            }

            setMsgMargin(position, 4, 2);
            mInitSetMap.put(position, true);
        }
    }

    /**
     * 显示未读红点
     *
     * @param position 显示tab位置
     */
    public void showDot(int position) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }
        showMsg(position, 0);
    }

    /** 隐藏未读消息 */
    public void hideMsg(int position) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }

        View tabView = mTabsContainer.getChildAt(position);
        MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
        if (tipView != null) {
            tipView.setVisibility(View.GONE);
        }
    }

细心的你一定会发现show并没有直接控制View的Visibility显示隐藏,而是用了UnreadMsgUtils,这个类提供了两个方法setSize和show方法,show方法对show的countSize进行了一次判断转换0为点,1-99圆+数字,>99则显示99+,背景的弧度为宽度的一半

再回到setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments)方法,在我们调用该方法时内部帮我们创建了内部定义的InnerPagerAdapter适配器,如果你想偷懒不想写适配器就可以调用这个方法。InnerPagerAdapter重写了getPageTitle,以便于notifyDataSetChanged方法调用动态添加tab项。

 class InnerPagerAdapter extends FragmentPagerAdapter {
        private ArrayList<Fragment> fragments = new ArrayList<>();
        private String[] titles;

        public InnerPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments, String[] titles) {
            super(fm);
            this.fragments = fragments;
            this.titles = titles;
        }

        @Override
        public int getCount() {
            return fragments.size();
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return titles[position];
        }

        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            // 覆写destroyItem并且空实现,这样每个Fragment中的视图就不会被销毁
            // super.destroyItem(container, position, object);
        }

        @Override
        public int getItemPosition(Object object) {
            return PagerAdapter.POSITION_NONE;
        }
    }

CommonTabLayout与上面SlidingTabLayout百分之99的相似度,重复的不在叙述,区别点在于setTabData和notifyDataSetChanged方法,notifyDataSetChanged根据Icon的Gravity属性进入不同布局的View做Tab,虽然TextView有drawableLeftRightTopBottom的相关属性,但是并不能让我们那么自由的控制Ui。

    /** 更新数据 */
    public void notifyDataSetChanged() {
        mTabsContainer.removeAllViews();
        this.mTabCount = mTabEntitys.size();
        View tabView;
        for (int i = 0; i < mTabCount; i++) {
            if (mIconGravity == Gravity.LEFT) {
                tabView = View.inflate(mContext, R.layout.layout_tab_left, null);
            } else if (mIconGravity == Gravity.RIGHT) {
                tabView = View.inflate(mContext, R.layout.layout_tab_right, null);
            } else if (mIconGravity == Gravity.BOTTOM) {
                tabView = View.inflate(mContext, R.layout.layout_tab_bottom, null);
            } else {
                tabView = View.inflate(mContext, R.layout.layout_tab_top, null);
            }

            tabView.setTag(i);
            addTab(i, tabView);
        }

        updateTabStyles();
    }

setTabData(ArrayList tabEntitys, FragmentActivity fa, int containerViewId, ArrayList fragments)方法内部初始化了一个Fragment的管理辅助类FragmentChangeManager,该类在构造函数动态添加隐藏了fragment,对外提供setFragments(int index)显示指定位置的Fragment,这个在frameLayout+Fragment+commonTabLayout布局里面免去了我们管理fagment的烦恼

SegmentTabLayout相比较于CommonTabLayout多了动画这块的处理,点击了某一项Tab,调用setCurrentTab,间接调用calcOffset开启了动画,动画的执行过程中onAnimationUpdate重新重绘,调整位置。

  tabView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = (Integer) v.getTag();
                if (mCurrentTab != position) {
                    setCurrentTab(position);
                    if (mListener != null) {
                        mListener.onTabSelect(position);
                    }
                } else {
                    if (mListener != null) {
                        mListener.onTabReselect(position);
                    }
                }
            }
        });

    //setter and getter
    public void setCurrentTab(int currentTab) {
        mLastTab = this.mCurrentTab;
        this.mCurrentTab = currentTab;
        updateTabSelection(currentTab);
        if (mFragmentChangeManager != null) {
            mFragmentChangeManager.setFragments(currentTab);
        }
        if (mIndicatorAnimEnable) {
            calcOffset();
        } else {
            invalidate();
        }
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        IndicatorPoint p = (IndicatorPoint) animation.getAnimatedValue();
        mIndicatorRect.left = (int) p.left;
        mIndicatorRect.right = (int) p.right;
        invalidate();
    }

小结

首先说一点这里不提供demo,需要去官方https://github.com/H07000223/FlycoTabLayout down ,其次呢这个库看了之后还是有很大收获的,比如自定义属性的运用, setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments)内部实例一个adapter适配器,最重要的是自定义属性解析和属性值代码设置通过一个类来代理完成。

开源项目: FlycoTabLayout SlidingTabLayout不显示字体的问题 异常: 导入优秀开源项目 FlycoTabLayout 使用后,Tab莫名其妙的不显示文字,头疼。 解决办法: 项目中存在两个layout_tab.xml文件 ,将其中一个布局文件重命名,只能这么办了。 下面是解决过程,如节省时间,可跳过。 经过一番断点调试发现: tv_tab_title 为null,这就很蛋疼了 private void addTab(final int position, String title, View tabView) { TextView tv_tab_title = tabView.findViewById(R.id.tv_tab_t 立即下载

相关推荐

全志Longan和Tina系统T113-S3-(Tina Linux 系统介绍)

Tina Linux是全志科技基于Linux内核开发的针对智能硬件类产品的嵌入式软件系统。Tina Linux基于openwrt-14.07 版本的软件开发包,包含了 Linux 系统开发用到的内核源码、驱动、工具、系统中间件与应用程序包。Tina系统软件架构如图所示。从下至上分别为Kernel && Driver、Libraries、System Services、Applications 四层。

szembed的博客 6332

TabLayout加强版 —— com.flyco.tablayout.SlidingTabLayout

TabLayout相信很多人都知道并且用过。一个很不错的Tab切换View,但是也存在一定问题。就是indicator(指示器)不能修改长短。这个功能让人很无语。关于这个问题的修改,网上有很多神仙方案。但是各有利弊。 所以。今天就来说一下 SlidingTabLayout,据说是google官方推荐的tab切换View。 好,不多说,老夫就是一把梭。直接上代码。 1、首先导入依赖 implemen...

lixinxiaos的博客 4551

VASP计算层错能(SFE)全攻略2

本文介绍了使用VASP计算纯镍(Ni)层错能(SFE)的具体步骤。首先构建Ni的FCC单胞并扩展为超胞,通过修改原子位置引入堆垛层错;随后分别计算完美晶体和含层错结构的能量;最后通过能量差与层错面积之比求得SFE值。计算需注意k点网格、截断能和超胞尺寸的收敛性测试,并推荐使用PAW赝势和ASE等工具辅助结构构建。

weixin_50519490的博客 1986

Android TabLayout 库:FlycoTabLayout

FlycoTabLayout 是一个一个安卓的Tablayout库,其中主要包含了CommonTabLayout,SegmenTabLayout,SlidingTabLayout。相信到这里就会有很多人问这是一个什么鬼,不说那么多直接上图,简单粗暴。 CommonTabLayout的用法: 1.布局 <ScrollView xmlns:android="h

LUFANZHENG的专栏 1万+

TCP Reno/CUBIC 拥塞控制算法对比:从 Tahoe 到 BBR 的 4 种核心策略演进

本文深入解析了TCP拥塞控制算法的演进历程,从经典的Tahoe、Reno到现代的CUBIC和BBR,详细对比了4种核心策略的实现机制与性能差异。通过分析拥塞窗口、流量控制等关键技术,揭示了不同算法在高带宽延迟网络中的优化方向,为网络协议栈优化提供理论依据和实践指导。

weixin_33725239的博客 439

EDA环境下的LSF进阶调优:如何为Cadence/VCS等工具正确配置cgroups与daemon starter

本文深入探讨了在EDA环境中如何为Cadence/VCS等工具正确配置LSF的cgroups与daemon starter,解决资源分配与特殊应用兼容性问题。通过详细解析cgroups技术、daemon starter配置及混合资源管理策略,帮助提升LSF集群的效率和稳定性,特别适用于高性能计算和芯片设计场景。

weixin_33724046的博客 461

开源项目: FlycoTabLayout——CommonTabLayout

http://blog.csdn.net/analyzesystem/article/details/51426473#comments

小北 5618

交换机背板带宽、交换容量与包转发率到底是啥?

在网络工程中,交换机是核心设备之一,而关于它的性能指标,背板带宽、交换容量、以及包转发率往往成为人们衡量其性能的重要参数。这些术语的定义、关系、以及在实际场景中的应用,都对交换机的选型与部署有着重要意义。本文将为您全面解读这些概念,帮助您深入了解交换机的核心性能指标。

网络技术联盟站 1548

开源项目: FlycoTabLayout (滑动指示器)

实现图片的效果 布局文件 <com.flyco.tablayout.SegmentTabLayout android:layout_centerInParent="true" android:id="@+id/segmenttablayout" android:layout_width="match_parent" android:lay

s779528166的博客 1875

需求跟踪详解

需求跟踪是指在软件项目开发过程中,建立并维护需求与项目各阶段工作产物(如设计文档、代码模块、测试用例等)之间对应关系的过程。它不仅记录需求从提出到实现的完整路径,还能反映需求变更时对各阶段工作的影响范围,是连接用户期望与实际软件开发产出的桥梁。

跟佟格湾一起学习计算机知识吧~ 1422

全志V3S嵌入式驱动开发(驱动开发准备)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 之前的文章都是教大家怎么搭建环境、看原理图、编译内核和根文件系统、做镜像,直到现在才进入驱动开发的主题。毕竟整个专栏的目的,还是希望大家能够学会驱动外部硬件。驱动好硬件,分成硬件和软件两个部分,硬件的部分比较好理解,就是看相关的信号有没有对接上即可,但是软件对接、甚至于怎么写软件,大家好像接触的比较少,所以这个时候,就可以简单讨论一下,怎么样才能写驱动代码。 1、了解外部驱动芯

嵌入式-老费,一个分享专业嵌入式知识的blog 2024

FlycoTabLayout_Lib的使用

FlycoTabLayout_Lib包含三种常用的效果:1.CommonTabLayout(文字,下划线点击切换效果)2.SegmentTabLayout(文字,按钮点击切换效果)3.SlidingTabLayout(可水平滑动切换效果)来一张官方示例的动图,感受一下本章只介绍CommonTabLayout的简单使用,另外两种实现方式请参阅Github源码介绍及demoStep1:在app的bui...

qq_32434817的博客 8536

PyTorch实战(25)——使用PyTorch构建DQN模型

深度Q网络 (Deep Q-learning Network, DQN) 在强化学习领域取得了巨大的成功和广泛的应用,PyTorch 结合 gymnasium 库为我们提供了强大的工具,支持在各种强化学习环境中测试不同类型的深度强化学习模型。在本节中,我们使用 PyTorch 框架构建使用卷积神经网络架构的 DQN 模型,模型通过自主学习掌握 Atari 经典游戏《Pong》的操作策略,最终实现击败电脑对手的竞技目标。

盼小辉丶的博客 3443

FlycoTabLayout使用

step1:在module.gradle中添加dependencies{ compile 'com.android.support:support-v4:23.1.1' compile 'com.nineoldandroids:library:2.4.0' compile 'com.flyco.roundview:FlycoRoundView_Lib:1.1.2@aar'

X小飞侠的博客 6733

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

FlycoTablayout:

1.依赖: //flycoTabLayout依赖 implementation ‘com.flyco.tablayout:FlycoTabLayout_Lib:2.0.2@aar’ 2.介绍: 1.FlycoTabLayout 是一个一个安卓的Tablayout库,其中主要包含了CommonTabLayout,SegmenTabLayout,SlidingTabLayout 2.CommonTab...

风尘的博客 721

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

FlycoTabLayout的使用

customTabEntities.add(new MyCustommRT("首页",R.drawable.ic_launcher_background,R.drawable.ic_launcher_background));customTabEntities.add(new MyCustommRT("首页",R.drawable.ic_launcher_background,R.drawable.ic_launcher_background));//定义commonTabLayout。

zk040221的博客 556

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

上一篇: Android开发之 混淆加固和反编译
下一篇: Android开发之内存管理
AnalyzeSystem
博客等级 码龄11年 204粉丝 114原创
评论 40
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值