仿淘宝Android实现底部导航栏图标溢出效果-clipChildren属性

1.clipChildren和clipPadding说明

  • clipChildren用来定义他的子控件是否要在他应有的边界内进行绘制。 默认情况下,clipChild被设置为true。 也就是不允许进行扩展绘制。
  • clipToPadding用来定义ViewGroup是否允许在padding中绘制。默认情况下,cliptopadding被设置为ture, 也就是把padding中的值都进行裁切了。

还有该功能是android第一个版本就已经提供的方法, 所有可以跨任意android版本使用;

这两个属性联合起来能干什么呢?用来做一些类似于心形放大等点击特效非常合适, 不用去更改布局, 只需加入这两个属相,并引入动画效果就完成了;

注意事项:

  • 只需在根节点设置android:clipChildren为false即可,默认为true,注意:一定是在布局文件的根节点设置,否则不起作用;
  • 可以通过android:layout_gravity控制超出的部分如何显示;
  • android:clipChildren的意思:是否限制子View在其范围内,我们将其值设置为false后那么当子控件的高度高于父控件时也会完全显示,而不会被压缩;

父视图设置android:clipChildrenandroid:clipPadding和不设置的效果如下:

仿淘宝Android实现底部导航栏图标溢出效果-clipChildren属性_第1张图片仿淘宝Android实现底部导航栏图标溢出效果-clipChildren属性_第2张图片

2.实例讲解

最近在写一个需求,要求点击底部栏的按钮,要能让图标放大,且要超出底部栏,实现一种越界的效果,效果如下:

仿淘宝Android实现底部导航栏图标溢出效果-clipChildren属性_第3张图片

 

 

 

2.1引入TabLayout库

android.surport.v4/v7项目中TabLayoutapp_module对应的build.gradle中的引用如下:

    //TabLayout
    compile 'com.android.support:design:27.1.1'
    compile 'com.android.support:support-v4:27.1.1'

androidx项目中TabLayoutapp_module对应的build.gradle中的引用如下:

    //TabLayout
    implementation 'com.google.android.material:material:1.2.0'

2.2定义布局

注意事项:根布局需要设置android:clipChildrenTabLayout布局android:clipChildren属性都需要设置为false,否则不生效;

根布局activity_main.xml




    
        
    

    
    

TabLayoutTab布局tab_item.xml



    
    

2.3关键代码实现

TabLayout动态添加Tab:

private void initViews() {
    mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
    initTabLayout();
}

private void initTabLayout(){
    //图文组合
    if(tabImageResource != null && tabImageResource.length > 0){
        createImageAndChina();
    }else if(tabTitles != null && tabTitles.length > 0){
        createChinaItem();
    }
}

/**
 * 创建图文混排Item
 */
private void createImageAndChina() {
    isImageAndChina = true;
    for (int i = 0; i < tabImageResource.length; i++) {
        TabLayout.Tab tab = mTabLayout.newTab();
        if(tab != null){
            tab.setCustomView(getTabView(i));
            mTabLayout.addTab(tab);
        }
    }
}

/**
 * 图文混排Item
 * @param position
 * @return
 */
private View getTabView(int position) {
    View tabView = LayoutInflater.from(this).inflate(R.layout.tab_item, null);
    setContentItem(tabView, position);
    return tabView;
}

选中Tab动态修改Tab的Margin使Tab超出TabLayout:

/**
 * 修改Tab视图Margin
 * @param customView
 * @param dimenId
 */
public void changeTabMargin(View customView,int dimenId){
    ViewGroup targetViewToApplyMargin = (ViewGroup) customView.getParent();
    ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) targetViewToApplyMargin.getLayoutParams();
    layoutParams.topMargin = (int)getResources().getDimension(dimenId);
    targetViewToApplyMargin.setLayoutParams(layoutParams);
}

选中Tab时实现Tab视图的放大缩小效果:

/**
 * 使用属性动画改变Tab中View的状态
 * @param customView
 */
private void changeTabSelect(View customView){
    View iV =  customView.findViewById(R.id.iv_app_icon);
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iV, "",1.0f,1.4f,1.0f)
            .setDuration(200);
    objectAnimator.start();
    objectAnimator.addUpdateListener(animation -> {
        float cVal = (Float) animation.getAnimatedValue();
        customView.setScaleY(cVal);
        customView.setScaleX(cVal);
    });
}

若有clipChilren属性不生效,可以动态设置Tab子视图的ViewGroup的clipChildren属性为false(暂未使用)

/**
 * 设置TabLayout下Tab父视图不裁剪子视图
 * @param customView
 */
public void changeClipFalse(View customView){
    if (customView != null) {
        ViewGroup targetViewToApplyMargin = (ViewGroup) customView.getParent();
        //循环设置Tab下父视图不裁剪超出部分子视图
        while (targetViewToApplyMargin != mTabLayout){
            targetViewToApplyMargin.setClipChildren(false);
            targetViewToApplyMargin.setClipToPadding(false);
            targetViewToApplyMargin = (ViewGroup)targetViewToApplyMargin.getParent();
        }
    }
}

github源码地址:mayundoyouknow / Tablayout · CODE CHINA

参考:

仿淘宝/漫画岛底部栏实现--解决TabLayout clipchildren属性无效问题--底部导航栏图标溢出实现 - 简书

ConstraintLayout 实现LinearLayout weight效果_wqbs369的专栏-CSDN博客

你可能感兴趣的:(Android面试整理2021,TabLayout,clipChildren)