android view 的创建解析,拦截view的创建并进行操作(二)

GIF1.gif

要做到这种动画效果我们需要用到捕获所有view并对view 进行一系列操作

上一节讲了了解了view的创建流程现,现在通过demo的形式来完成此功能

首先创建一个framgment 来实现LayoutInflaterFactory接口,这一步骤做完 所有的view都会走接口中的方法了,可以照抄系统的源码一直往下走 AppCompatViewInflater 这个类发现是new不出来的,直接把这个类的内容复制出来我们新建一个类命名相同,这样整个fragment内的布局里面的view都会走我们自己的方法


        //我重新复制一个LayoutInflater ,因为LayoutInflater是单例 否则下面会报错
        LayoutInflater layoutInflater = inflater.cloneInContext(getActivity());

        LayoutInflaterCompat.setFactory(layoutInflater, this);

        return layoutInflater.inflate(mlayoutId, container, false);
        
    实现接口所调用的方法
    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {

        View view = createView(parent, name, context, attrs);
        if (view != null) {
            // Log.e("TAG", "我来创建View");
            // 解析所有的我们自己关注属性
            analysisAttrs(view, context, attrs);
        }
        return view;
    }
    
        public View createView(View parent, final String name, @NonNull Context context,
                           @NonNull AttributeSet attrs) {
        final boolean isPre21 = Build.VERSION.SDK_INT < 21;

        if (mAppCompatViewInflater == null) {
            mAppCompatViewInflater = new AppCompatViewInflater();
        }

        // We only want the View to inherit it's context if we're running pre-v21
        final boolean inheritContext = isPre21 && true
                && shouldInheritContext((ViewParent) parent);

        return mAppCompatViewInflater.createView(parent, name, context, attrs, inheritContext,
                isPre21, /* Only read android:theme pre-L (L+ handles this anyway) */
                true /* Read read app:theme as a fallback at all times for legacy reasons */
        );
    }

    private boolean shouldInheritContext(ViewParent parent) {
        if (parent == null) {
            // The initial parent is null so just return false
            return false;
        }
        while (true) {
            if (parent == null) {
                // Bingo. We've hit a view which has a null parent before being terminated from
                // the loop. This is (most probably) because it's the root view in an inflation
                // call, therefore we should inherit. This works as the inflated layout is only
                // added to the hierarchy at the end of the inflate() call.
                return true;
            } else if (ViewCompat.isAttachedToWindow((View) parent)) {
                // We have either hit the window's decor view, a parent which isn't a View
                // (i.e. ViewRootImpl), or an attached view, so we know that the original parent
                // is currently added to the view hierarchy. This means that it has not be
                // inflated in the current inflate() call and we should not inherit the context.
                return false;
            }
            parent = parent.getParent();
        }
    }

    //获取所有的view 并拿到view中的参数 设置到tag中 通过viewpager的滑动而一起滑动
    private void analysisAttrs(View view, Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, mAttrs);
        if (view != null && typedArray.getIndexCount() != 0) {
            int n = typedArray.getIndexCount();
            ParallaxTag parallaxTag = new ParallaxTag();
            for (int i = 0; i <= n; i++) {
                int attr = typedArray.getIndex(i);
                switch (attr) {
                    case 0:
                        parallaxTag.translationXIn = typedArray.getFloat(attr, 0f);
                        break;
                    case 1:
                        parallaxTag.translationXOut = typedArray.getFloat(attr, 0f);
                        break;
                    case 2:
                        parallaxTag.translationYIn = typedArray.getFloat(attr, 0f);
                        break;
                    case 3:
                        parallaxTag.translationYOut = typedArray.getFloat(attr, 0f);
                        break;
                }
            }
            view.setTag(R.id.parallax_tag,parallaxTag);
            parallaxView.add(view);
            Log.e("TAG",parallaxTag.toString());
        }
        typedArray.recycle();
    }
    
    
    

上面的代码已经把所有的view拿到,现在自定义一个viewpager实现监听接口

  addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

                Log.e("TAG","position->"+position+" positionOffset->"+positionOffset+" positionOffsetPixels->"+positionOffsetPixels);
                ParallaxFragment outFragment = (ParallaxFragment) mFragmentList.get(position);
                List parallaxViewsOut = outFragment.getParallaxView();
                for (View parallaxView : parallaxViewsOut) {
                    ParallaxTag tag = (ParallaxTag) parallaxView.getTag(R.id.parallax_tag);
                    parallaxView.setTranslationX((- positionOffsetPixels) * tag.translationXOut);
                    parallaxView.setTranslationY((- positionOffsetPixels) * tag.translationYOut);
                }
                try {
                    ParallaxFragment inFragment = (ParallaxFragment) mFragmentList.get(position+1);

                    List parallaxViewsIn = inFragment.getParallaxView();
                    for (View parallaxView : parallaxViewsIn) {
                        ParallaxTag tag = (ParallaxTag) parallaxView.getTag();
                        parallaxView.setTranslationX(( positionOffsetPixels) * tag.translationXIn);
                        parallaxView.setTranslationY((positionOffsetPixels) * tag.translationYIn);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

使用方法

        mParallaxViewPager = (ParallaxViewPager) findViewById(R.id.viewpager);
mParallaxViewPager.setLayout(new int[]
              {R.layout.fragment_page_first, R.layout.fragment_page_second, 
                        R.layout.fragment_page_third}, getSupportFragmentManager());

demo地址

你可能感兴趣的:(android view 的创建解析,拦截view的创建并进行操作(二))