android客户端首次进入轮播引导图(一)
16lz
2021-01-23
先来看一下效果图:
有时一小块不起眼的功能就需要好多代码完成,这个可以做成框架用的,我这里仅仅在自己的app里使用了,这里还要感谢一下谷歌。来看一下借用的谷歌的代码:
// Since this is an object collection, use a FragmentStatePagerAdapter,// and NOT a FragmentPagerAdapter.public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter { public DemoCollectionPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { Fragment fragment = new DemoObjectFragment(); Bundle args = new Bundle(); // Our object is just an integer :-P args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1); fragment.setArguments(args); return fragment; } @Override public int getCount() { return 100; } @Override public CharSequence getPageTitle(int position) { return "OBJECT " + (position + 1); }}
挺好用的,嘿嘿。。。
好了看一下我的代码,我这里用的基本上就一个fragement+viewpager,先看一下activity的代码,我写的时候没有加注释,而且把调试代码删了。。。
首次进入轮播图其实不难,不建议用别人的依赖,核心代码不超过二百行。
package com.fanyafeng.recreation.activity;import android.content.Intent;import android.graphics.Matrix;import android.os.Bundle;import android.support.design.widget.FloatingActionButton;import android.support.design.widget.Snackbar;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentStatePagerAdapter;import android.support.v4.view.ViewCompat;import android.support.v4.view.ViewPager;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.util.DisplayMetrics;import android.util.Log;import android.view.View;import android.view.ViewTreeObserver;import android.widget.Button;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RadioButton;import android.widget.RadioGroup;import android.widget.RelativeLayout;import com.fanyafeng.recreation.R;import com.fanyafeng.recreation.BaseActivity;import com.fanyafeng.recreation.fragment.StartPagerFragment;import com.fanyafeng.recreation.util.MyUtils;import java.util.ArrayList;import java.util.List;//需要搭配Baseactivity,这里默认为Baseactivity,并且默认BaseActivity为包名的根目录public class FirstStartActivity extends BaseActivity { private ViewPager startViewPager; private StartPagerAdapter startPagerAdapter; private List fragmentList = new ArrayList<>(); private Button btnFirstStart; private int maxX = 0; private ImageView ivMovementCircle; private static int[] startPage = new int[]{R.drawable.start_one, R.drawable.start_two, R.drawable.start_three, R.drawable.start_four, R.drawable.start_five}; private int totalSize = 5; private RelativeLayout layoutStartRoot; private float moveCircleY = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first_start); //这里默认使用的是toolbar的左上角标题,如果需要使用的标题为中心的采用下方注释的代码,将此注释掉即可 title = getString(R.string.title_activity_first_start); isShowToolbar = false; initView(); initData(); initCursorPosition(); } //初始化UI控件 private void initView() { layoutStartRoot = (RelativeLayout) findViewById(R.id.layoutStartRoot); ivMovementCircle = (ImageView) findViewById(R.id.ivMovementCircle); btnFirstStart = (Button) findViewById(R.id.btnFirstStart); startViewPager = (ViewPager) findViewById(R.id.startViewPager); for (int i = 0; i < totalSize; i++) { fragmentList.add(new StartPagerFragment()); } } private void initCursorPosition() { DisplayMetrics displayMetrics = new DisplayMetrics(); this.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); final int width = displayMetrics.widthPixels; maxX = width; Matrix matrix = new Matrix(); matrix.postTranslate(width / (totalSize + 1) - MyUtils.dip2px(this, 4), 0); ivMovementCircle.setImageMatrix(matrix); ivMovementCircle.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (ivMovementCircle.getY() != 0) { moveCircleY = ivMovementCircle.getY(); for (int i = 0; i < totalSize; i++) { ImageView imageView = new ImageView(FirstStartActivity.this); imageView.setImageDrawable(getResources().getDrawable(R.drawable.white_shape_circle)); imageView.setX(width / (totalSize + 1) * (i + 1) - MyUtils.dip2px(FirstStartActivity.this, 3)); imageView.setY(moveCircleY); layoutStartRoot.addView(imageView); ivMovementCircle.bringToFront(); } } else { return; } ivMovementCircle.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); } //初始化数据 private void initData() { startPagerAdapter = new StartPagerAdapter(getSupportFragmentManager(), fragmentList); startViewPager.setAdapter(startPagerAdapter); startViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (maxX != 0 && positionOffsetPixels != 0) { float alph = 255 * positionOffsetPixels / maxX; if (position == totalSize - 2) { btnFirstStart.setVisibility(View.VISIBLE); btnFirstStart.getBackground().setAlpha((int) alph); btnFirstStart.setAlpha(alph); } else { btnFirstStart.setVisibility(View.GONE); } } if (positionOffsetPixels != 0) { ViewCompat.setTranslationX(ivMovementCircle, maxX / (totalSize + 1) * position + positionOffsetPixels / (totalSize + 1)); } } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } }); } class StartPagerAdapter extends FragmentStatePagerAdapter { private List fragmentList; public StartPagerAdapter(FragmentManager fm, List fragmentList) { super(fm); this.fragmentList = fragmentList; } @Override public Fragment getItem(int position) { Bundle bundle = new Bundle(); bundle.putString("param1", String.valueOf(position)); bundle.putInt("param2", startPage[position]); Fragment fragment = fragmentList.get(position); fragment.setArguments(bundle); return fragment; } @Override public int getCount() { return fragmentList.size(); } } @Override public void onClick(View v) { super.onClick(v); switch (v.getId()) { case R.id.btnFirstStart: finish(); break; case R.id.btnFirstFinish: finish(); break; } startActivity(new Intent(this, MainActivity.class)); }}
这里难点就两个吧,一个是让指示器的点随手势移动,一个是按钮的渐变,图片的加载交给fresco了。其实抽象一下就是获取偏移量,再根据轮播图的个数去进行处理。
这里点开看一下源码:
/** * Callback interface for responding to changing state of the selected page. */ public interface OnPageChangeListener { /** * This method will be invoked when the current page is scrolled, either as part * of a programmatically initiated smooth scroll or a user initiated touch scroll. * * @param position Position index of the first page currently being displayed. * Page position+1 will be visible if positionOffset is nonzero. * @param positionOffset Value from [0, 1) indicating the offset from the page at position. * @param positionOffsetPixels Value in pixels indicating the offset from position. */ void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); /** * This method will be invoked when a new page becomes selected. Animation is not * necessarily complete. * * @param position Position index of the new selected page. */ void onPageSelected(int position); /** * Called when the scroll state changes. Useful for discovering when the user * begins dragging, when the pager is automatically settling to the current page, * or when it is fully stopped/idle. * * @param state The new scroll state. * @see ViewPager#SCROLL_STATE_IDLE * @see ViewPager#SCROLL_STATE_DRAGGING * @see ViewPager#SCROLL_STATE_SETTLING */ void onPageScrollStateChanged(int state); }
这里先去看一下英文,然后再去打log看一下调试信息就是到具体代表什么了,这里不是很建议用positionOffset这个偏移的比例,稍微有点坑,再有就是view的移动,这里用了一下v4包里的方法:
/** * Sets the horizontal location of this view relative to its left position. * This effectively positions the object post-layout, in addition to wherever the object's * layout placed it. * * Prior to API 11 this will have no effect.
* * @param value The horizontal position of this view relative to its left position, * in pixels. */ public static void setTranslationX(View view, float value) { IMPL.setTranslationX(view, value); }
再来看一下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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layoutStartRoot" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.fanyafeng.recreation.activity.FirstStartActivity" tools:showIn="@layout/activity_first_start"> <android.support.v4.view.ViewPager android:id="@+id/startViewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:id="@+id/btnFirstFinish" android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:background="@drawable/avatar_round_bg" android:text="跳过" android:onClick="onClick" android:textColor="@android:color/white" android:textSize="12dp" /> <Button android:id="@+id/btnFirstStart" android:layout_width="100dp" android:layout_height="40dp" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:layout_marginBottom="40dp" android:background="@drawable/rounded_button_bg" android:text="开始" android:onClick="onClick" android:textColor="@android:color/white" android:visibility="gone" /> <ImageView android:id="@+id/ivMovementCircle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="10dp" android:scaleType="matrix" android:src="@drawable/shape_circle" />RelativeLayout>
我这里的可移动指示点是定义在xml的,并没有去new,因为可以动的就一个是固定的,但是不可动的背景是不确定的,我去new的,还有个注意的地方就是高度的获取,就是需要了解一下android的绘画机制,需要进行两次测量才能确定view的高度进行绘制:
ivMovementCircle.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (ivMovementCircle.getY() != 0) { moveCircleY = ivMovementCircle.getY(); for (int i = 0; i < totalSize; i++) { ImageView imageView = new ImageView(FirstStartActivity.this); imageView.setImageDrawable(getResources().getDrawable(R.drawable.white_shape_circle)); imageView.setX(width / (totalSize + 1) * (i + 1) - MyUtils.dip2px(FirstStartActivity.this, 3)); imageView.setY(moveCircleY); layoutStartRoot.addView(imageView); ivMovementCircle.bringToFront(); } } else { return; } ivMovementCircle.getViewTreeObserver().removeGlobalOnLayoutListener(this); } });
这里设置了监听以后记得去remove掉,尤其有多个的时候。
ok,再来看一下fragment,这里没什么难的,就收参数然后去进行展示:
package com.fanyafeng.recreation.fragment;import android.content.Context;import android.net.Uri;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import com.facebook.drawee.view.SimpleDraweeView;import com.fanyafeng.recreation.R;import com.fanyafeng.recreation.util.FrescoUtil;public class StartPagerFragment extends Fragment { private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; private String mParam1; private int mParam2; private SimpleDraweeView sdvStart; public StartPagerFragment() { // Required empty public constructor } public static StartPagerFragment newInstance(String param1, int param2) { StartPagerFragment fragment = new StartPagerFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putInt(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getInt(ARG_PARAM2); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_start_pager, container, false); sdvStart = (SimpleDraweeView) view.findViewById(R.id.sdvStart); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); FrescoUtil.loadGifPicInApp(sdvStart, mParam2); }}
xml也很简单:
"http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.fanyafeng.recreation.fragment.StartPagerFragment"> <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdvStart" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/hello_blank_fragment" />
更多相关文章
- [Tools]Android Studio代码提示功能--Ctrl+Alt+Space(空格键)
- Android学习心得(14) --- Android代码混淆(2)
- 一网打尽__Android 开源代码合集(SwitchButton)
- DSBridge——一套H5代码就能同时与Android和iOS通信
- [原创]通过代码及流程图说明Google在Android上的Push机制的实现
- Android Studio xml android标签突然没有代码提示问题的解决
- Android填坑之旅(第十七篇)MIX2 适配看这一篇就够了,只需一行代码
- Android 代码实现查看SQLite数据库中的表
- android的代码性能优化