Android UI 启动页平行动画

Android UI 启动页平行动画

应用启动页面实现类似小红书平行动画功能

实现思路
  1. 采用ViewPager实现滑动复用引导Fragment
// 展示引导Activity
public class GuideAct extends FragmentActivity {

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

        ParallaxContainer container = findViewById(R.id.parallax_container);
        // 主要准备一些引导Fragment页面,传递给ParallaxContainer,设置为ViewPager子Fragment布局
        container.setUp(new int[]{
                R.layout.view_intro_1,
                R.layout.view_intro_2,
                ......
        });
}

}
  1. 看下引导 guide_act.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <cn.cutcopy.anim.ParallaxContainer
        ......>
    </cn.cutcopy.anim.ParallaxContainer>

</RelativeLayout>

单个Fragment上引导介绍元素 view_intro_1.xml,其他引导页类似

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ...... >
   <!-- 自定义属性,可以在自定义LayoutInflater中获取 -->
    <ImageView
        android:id="@+id/iv_0"
        android:layout_width="103dp"
        ......
        app:x_in="1.2"
        app:x_out="1.2" />

</RelativeLayout>
  1. ParallaxContainer.java (添加ViewPager实现左右滑动引导)
public class ParallaxContainer extends FrameLayout implements ViewPager.OnPageChangeListener {

    private static final String TAG = "ParallaxContainer";

    private List<ParallaxFragment> fragments;
    private ParallaxPagerAdapter adapter;

    ......
    
    public void setUp(int... childIds) {
        // Fragment数组
        fragments = new ArrayList<>();
        for (int i = 0; i < childIds.length; i++) {
            ParallaxFragment f = new ParallaxFragment();
            Bundle args = new Bundle();
            // Fragment中需要加载的布局文件id
            args.putInt("layoutId", childIds[i]);
            f.setArguments(args);
            fragments.add(f);
        }

        ViewPager vp = new ViewPager(getContext());
        vp.setId(R.id.parallax_pager);
        //实例化适配器
        GuideAct activity = (GuideAct) getContext();
        adapter = new ParallaxPagerAdapter(activity.getSupportFragmentManager(), fragments);
        ......
        vp.setOnPageChangeListener(this);
        addView(vp, 0);
    }

	// 滑动引导页面,这个方法在滑动过程中会一直调用,
	// 此时就可以通过这里positionOffsetPixels偏移值,另外配合每个Fragment上各个View在xml中app:x_in="1.2" 设置的偏移系数,开始执行Fragment上元素位移动画
	// 每个Fragment上元素通过 ==自定义属性== 配合 [动画辅助库](https://github.com/JakeWharton/NineOldAndroids)达到动画偏移效果
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        Log.i(TAG, "onPageScrolled position : " + position);
        Log.i(TAG, "onPageScrolled positionOffset : " + positionOffset);
        Log.i(TAG, "onPageScrolled positionOffsetPixels : " + positionOffsetPixels);
        int containerWidth = getWidth();
        ParallaxFragment outFragment = null;
        try {
            outFragment = fragments.get(position - 1);
        } catch (Exception e) {}
        //获取到退出的页面
        ParallaxFragment inFragment = null;
        try {
            inFragment = fragments.get(position);
        } catch (Exception e) {}
        ......
    }

    @Override
    public void onPageSelected(int position) {
        Log.i(TAG, "onPageSelected position : " + position);
		......
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        Log.i(TAG, "onPageScrollStateChanged state : " + state);
		......
		// 执行开始或结束动画
    }
}

  1. 单个引导Fragment
// 视差Fragment
public class ParallaxFragment extends Fragment {

    private List<View> parallaxViews = new ArrayList<>();

    @Override
    public View onCreateView(LayoutInflater original, ViewGroup container,
                             Bundle savedInstanceState) {
        Bundle args = getArguments();
        int layoutId = args.getInt("layoutId");
        // 通过自定义LayoutInflater返回给Fragment布局
        ParallaxLayoutInflater inflater = new ParallaxLayoutInflater(original, getActivity(),this);
        return inflater.inflate(layoutId, null);
    }

    public List<View> getParallaxViews() {
        return parallaxViews;
    }
}
  1. 主要是通过 自定义LayoutInflater,获取到Fragment上系统或自定义View的滑动系数进行动画偏移

自定义LayoutInflater

public class ParallaxLayoutInflater extends LayoutInflater {

    private ParallaxFragment fragment;

    protected ParallaxLayoutInflater(Context context) {
        super(context);
    }

    protected ParallaxLayoutInflater(LayoutInflater original, Context newContext) {
        super(original, newContext);
    }

    protected ParallaxLayoutInflater(LayoutInflater original, Context newContext, ParallaxFragment fragment) {
        super(original, newContext);
        this.fragment = fragment;
        setFactory2(new ParallaxFactory(this));
    }

    @Override
    public LayoutInflater cloneInContext(Context context) {
        return new ParallaxLayoutInflater(this, context, fragment);
    }

    // 自定义一个加载View 的Factory
    class ParallaxFactory implements Factory2 {

        private LayoutInflater inflater;

        public ParallaxFactory(LayoutInflater inflater) {
            this.inflater = inflater;
        }

        // 在这里可以获取到view_intro_1.xml 中所有View设置的自定义或非自定义属性值
        @Override
        public View onCreateView(View parent, String name, Context context, AttributeSet attributeSet) {
            View view;
            ......
            return view;
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初心一点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值