其实这篇文章早就想写了,一直没空,马上就要出差了,于是想在出差前把这个赶紧写出来,要不真是到猴年马月了。
首先一张gif镇楼,无图无真相,只有图才能让你看到我今天要写的内容是什么,也不浪费各位大佬的时间。
这是我们的Ui 设计的一款 APP 引导图,其实刚定下这个需求的时候,我们的UI 已经自己把这个效果在ProtoPie 上 效果给做出来了。
当时还在忙其他的事情,第一眼看到他 给的这个效果,瞬间感觉懵逼了,看似简单,其中的左右两个色块是要跟着联动的,而且 除了左右的2个色块,其他的所有元素
都是要 渐变的。 而且不是单一的一个动画的渐变,是要根据Viewpager 的滑动 的量来 动态设置 透明度,可能我这个gif不太明显吧。
总的来说,对我这个菜鸟是一个挑战。因为那时候我 的实习期刚 结束,我自己的基础,还有这些组件的原理都不清楚。 觉得好有压力。但是后来,我看到我们的ios 小伙伴已经吧这个效果搞出来了,我特么瞬间就来脾气了,不服气,Android 怎么能输给 IOS,MMP。说干就干。 然后专心 一点一点的调试效果。出乎我自己的意料。一下午不到,这个效果就出来了。堪称我最 得以的一个模块了。
废话不多说,开始讲解,其实ViewPager 大家都 在熟悉不过了,基本用的都是监听这个onPageScrolled (int position,float positionOffset ,int positionOffsetPixels)
分别 position -->当前页面,即点击滑动的页面 ; positionOffset--> 当前页面偏移的百分比 ; positionOffsetPixels --> 当前页面偏移的像素位置
然后主要我使用的是 前2个参数。来达到这个效果。
首先是布局XML
主要的图片 贴下
然后其他的看代码就都能看懂了。
问题就在于如果 很好的移动这些简单的布局 元素,然后 达到产品和UI 想要的效果。
重点来了, 先贴重点代码。
mViewPage.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
setIndicatePoints(position);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
setTextAnimation(position, positionOffset);// 文案
setViewPagerPicAlpha(position,positionOffset);//Viewpager
if (position == 2) mll_Points_layout.setAlpha(1 - positionOffset);// 指示器 layout
// 背景(黄 白)色块
mIv_left_pic.setTranslationX(-(EVERY_OFFSET_X_SUM * (positionOffset + position)));
mIv_right_pic.setTranslationX(EVERY_OFFSET_X_SUM * (positionOffset + position));
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
没错,就这么点,就是整个 gif 的效果 。
其实最早 就是这2句代码,后期经过 不断的测试和 测试,然后以此类推 其他的也就不难了
// 背景(黄 白)色块
mIv_left_pic.setTranslationX(-(EVERY_OFFSET_X_SUM * (positionOffset + position)));
mIv_right_pic.setTranslationX(EVERY_OFFSET_X_SUM * (positionOffset + position));
GuideActivity.java
/**
* GDU pro guidepage 引导页
*/
public class GuideActivity extends Activity {
// pager 页数
private final static int PAGE_COUNT = 4;
// 指示灯 个数
private final static int DOT_COUNT = 3;
// 1208 x 720 的标准位移 量(UI 给)
private float X_OFFSET = 124;
// 因为是4个 pager 但是只位移了 3次,
private float MOVE_PERCENT = 1.444f;
// 每一个pager 位移X 的总量
private float EVERY_OFFSET_X_SUM;
// 基本元素
private View[] mPoints = new View[DOT_COUNT];
private PageView mPageViews[] = new PageView[PAGE_COUNT];
// find view
// 文案的个数
private TextView content01, content02, content03;
private MyPageAdapter myPagerAdapter;
private LinearLayout mll_Points_layout;
private ViewPager mViewPage;
private ImageView mIv_left_pic;
private ImageView mIv_right_pic;
// 帮助类
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.guidepage_gdupro_layout);
initView();
initData();
initViewPager();
setIndicatePoints(0);// 设置第一个指示点
setTextAnimation(0, 0);// 设置 text 文案
}
private void initView() {
content01 = (TextView) findViewById(R.id.tv_guidepage_content01);
content02 = (TextView) findViewById(R.id.tv_guidepage_content02);
content03 = (TextView) findViewById(R.id.tv_guidepage_content03);
content02.setAlpha(0);
content03.setAlpha(0);
mIv_left_pic = ((ImageView) findViewById(R.id.iv_guidepage_left_colorlump));
mIv_right_pic = ((ImageView) findViewById(R.id.iv_guidepage_right_colorlump));
mViewPage = (ViewPager) findViewById(R.id.guidepage_viewpager_gdu_pro);
mll_Points_layout = ((LinearLayout) findViewById(R.id.ll_guidepage_dots_layout));
mPoints[0] = findViewById(R.id.guide_v_dot1);
mPoints[1] = findViewById(R.id.guide_v_dot2);
mPoints[2] = findViewById(R.id.guide_v_dot3);
}
private void initData() {
// 根据手机屏幕大小算出 图片块的偏移量
X_OFFSET = (UavStaticVar.screenWidth /UavStaticVar.screenHeight) * X_OFFSET;
// 计算一个 pager 页面需要偏移的总量
EVERY_OFFSET_X_SUM = X_OFFSET * MOVE_PERCENT;
}
/**
* viewpager 事件
*/
private void initViewPager() {
mPageViews[0] = new PageView(R.mipmap.guidepage_viewpage1_cn, R.mipmap.guidepage_viewpage1_en);
mPageViews[1] = new PageView(R.mipmap.guidepage_viewpage2_cn, R.mipmap.guidepage_viewpage2_en);
mPageViews[2] = new PageView(R.mipmap.guidepage_viewpage3, R.mipmap.guidepage_viewpage3);
mPageViews[3] = new PageView(R.mipmap.guidepage_viewpage4, R.mipmap.guidepage_viewpage4);
myPagerAdapter = new MyPageAdapter();
mViewPage.setAdapter(myPagerAdapter);
mViewPage.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
setIndicatePoints(position);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
setTextAnimation(position, positionOffset);// 文案
setViewPagerPicAlpha(position,positionOffset);//Viewpager
if (position == 2) mll_Points_layout.setAlpha(1 - positionOffset);// 指示器 layout
// 背景(黄 白)色块
mIv_left_pic.setTranslationX(-(EVERY_OFFSET_X_SUM * (positionOffset + position)));
mIv_right_pic.setTranslationX(EVERY_OFFSET_X_SUM * (positionOffset + position));
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 引导页 文字显示 的 渐变 出现和显示
*
* @param currentPosition
* @param positionOffset
*/
public void setTextAnimation(int currentPosition, float positionOffset) {
if (currentPosition == 0) {
content01.setVisibility(View.VISIBLE);
content01.setAlpha(1 - positionOffset);
content02.setAlpha(positionOffset);
} else if (currentPosition == 1) {
content02.setVisibility(View.VISIBLE);
content02.setAlpha(1 - positionOffset);
content03.setAlpha(positionOffset);
} else if (currentPosition == 2) {
content03.setAlpha(1 - positionOffset);
content03.setVisibility(View.VISIBLE);
} else {
content01.setVisibility(View.GONE);
content02.setVisibility(View.GONE);
content03.setVisibility(View.GONE);
}
}
/**
* 设置图片的Alpha
*/
public void setViewPagerPicAlpha(int currentPosition, float positionOffset) {
if (currentPosition == 0) {
mPageViews[0].getiPageView().setAlpha(1 - positionOffset);
mPageViews[1].getiPageView().setAlpha(positionOffset);
} else if (currentPosition == 1) {
mPageViews[1].getiPageView().setAlpha(1 - positionOffset);
mPageViews[2].getiPageView().setAlpha(positionOffset);
} else if (currentPosition == 2) {
mPageViews[2].getiPageView().setAlpha(1 - positionOffset);
mPageViews[3].getiPageView().setAlpha(positionOffset);
}
}
/**
* 指示点 显示
*
* @param currentPosition
*/
public void setIndicatePoints(int currentPosition) {
for (int i = 0; i < mPoints.length; i++) {
if (currentPosition == i) {
mPoints[i].setSelected(true);
} else {
mPoints[i].setSelected(false);
}
}
if (currentPosition == 3) {
mPoints[2].setSelected(true);
}
}
/**
* Viewpager 适配器
*/
private class MyPageAdapter extends PagerAdapter {
@Override
public int getCount() {
if (null != mPageViews) {
return mPageViews.length;
}
return 0;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mPageViews[position].getiPageView());
return mPageViews[position].getiPageView();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mPageViews[position].getiPageView());
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
private class PageView {
private View iPageView;
public PageView(int cn_resid, int en_resid) {
iPageView = View.inflate(getBaseContext(), R.layout.guidepage_gdupro_viewpager_item, null);
ImageView imageView = (ImageView) iPageView.findViewById(R.id.Iv_guidepage_item_pic);
ImageView clickOpen = (ImageView) iPageView.findViewById(R.id.Tv_guidepage_in_app);
if (UavStaticVar.LanguageType.equals("zh")) {
imageView.setImageResource(cn_resid);
} else {
imageView.setImageResource(en_resid);
}
if (cn_resid == R.mipmap.guidepage_viewpage4) {
clickOpen.setVisibility(View.VISIBLE);
clickOpen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent in = new Intent(getBaseContext(), MainActivity2.class);
in.putExtra(MainActivity2.IsOnceCreate_label, true);
startActivity(in);
finish();
}
});
} else {
clickOpen.setVisibility(View.GONE);
}
}
public View getiPageView() {
return iPageView;
}
}
}
好了,暂且就先些这么多,等出差回来,有时间,在把自己觉得有意思的东西,总结下,记录下,万一有和我一样的菜鸟 遇到同样的问题呢,
最后BB 一句,我的大佬师傅说,一些效果能 自己写就自己去写,去研究,不要依赖第三方库,因为当APP 里面的内容大到一定程度的时候,你才考虑到代码的优化,或者出现内存的泄露,以及安装时候就出现 org.gradle.jvmargs=-Xmx4608M 不足,那时候在想着优化,重构就显得很麻烦 很耗费人力 ,精力了。
还有写代码的习惯一定要早早的养成,反正我觉得 多写点注释没毛病, 一是可以给 小白 用,二是 :可以让别人快速的阅读的你的代码,不会因为你某个 奇葩的 方法名字或者变量名字 想半天。 三是:以后你自己看的时候 更是能一下知道自己 以前 在哪里遇到坑了。问题的原因。
我就是废话比较多的那种人。谢谢观赏。