使用的布局使用的是GitHub:https://github.com/Cleveroad/slidingtutorial-android

第一步:添加:compile ‘com.android.support:percent:25.3.1’

第二步:布局

  • fragment_page_first
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout 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/rootFirstPage"android:layout_width="match_parent"android:layout_height="match_parent"tools:background="@android:color/holo_orange_dark"tools:ignore="ContentDescription"><ImageView
        android:id="@+id/ivFirstImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@mipmap/s_0_1"app:layout_heightPercent="35%"app:layout_widthPercent="50%"app:translationXIn="0.4"app:translationYIn="0.4"app:translationYOut="0.4"app:translationXOut="0.4" /><ImageView
        android:id="@+id/ivSecondImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentEnd="true"android:layout_alignParentRight="true"android:src="@mipmap/s_0_2"app:layout_heightPercent="10%"app:layout_marginRightPercent="12%"app:layout_marginTopPercent="27%"app:layout_widthPercent="12%"app:translationXIn="0.12"app:translationYIn="0.82"app:translationYOut="0.82"app:translationXOut="0.12" /><ImageView
        android:id="@+id/ivThirdImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_0_3"app:layout_heightPercent="25%"app:layout_marginLeftPercent="14%"app:layout_marginTopPercent="49%"app:layout_widthPercent="30%"app:translationXIn="0.16"app:translationXOut="0.16" /><ImageView
        android:id="@+id/ivFourthImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_0_4"app:layout_heightPercent="15%"app:layout_marginLeftPercent="14%"app:layout_marginTopPercent="39%"app:layout_widthPercent="20%"app:translationXIn="0.02"app:translationXOut="0.02" /><ImageView
        android:id="@+id/ivFifthImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:src="@mipmap/s_0_5"app:layout_heightPercent="15%"app:layout_marginTopPercent="22%"app:layout_widthPercent="45%"app:translationXIn="0.06"app:translationXOut="0.06" /><ImageView
        android:id="@+id/ivSixthImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_0_6"app:layout_heightPercent="6%"app:layout_marginLeftPercent="4%"app:layout_marginTopPercent="26%"app:layout_widthPercent="6%"app:translationXIn="0.18"app:translationXOut="0.18" /><ImageView
        android:id="@+id/ivSeventhImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_0_7"app:layout_heightPercent="8%"app:layout_marginLeftPercent="14%"app:layout_marginTopPercent="25%"app:layout_widthPercent="9%"app:translationXIn="0.28"app:translationXOut="0.28" /><ImageView
        android:id="@+id/ivEighthImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_0_8"app:layout_heightPercent="6%"app:layout_marginLeftPercent="77%"app:layout_marginTopPercent="38%"app:layout_widthPercent="8%"app:translationXIn="0.34"app:translationXOut="0.34" /><TextView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:gravity="center"android:text="@string/text_web_ceo"android:textColor="@android:color/white"android:textSize="@dimen/text_size_large"app:layout_heightPercent="15%"app:layout_marginBottomPercent="11%"app:layout_widthPercent="45%" />
</android.support.percent.PercentRelativeLayout>
  • fragement_page_second
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout
    android:id="@+id/rootSecondPage"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:layout_width="match_parent"android:layout_height="match_parent"tools:ignore="ContentDescription"tools:background="@android:color/holo_green_dark"><ImageView
        android:id="@+id/ivFirstImage"app:translationXIn="0.4"app:translationXOut="0.4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@mipmap/s_1_1"app:layout_heightPercent="25%"app:layout_widthPercent="45%"/><ImageView
        android:id="@+id/ivSecondImage"app:translationXIn="1.2"app:translationXOut="1.2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentEnd="true"android:layout_alignParentRight="true"android:alpha=".5"android:src="@mipmap/s_1_2"app:layout_heightPercent="6%"app:layout_marginRightPercent="14%"app:layout_marginTopPercent="30%"app:layout_widthPercent="19%"/><ImageView
        android:id="@+id/ivThirdImage"app:translationXIn="0.16"app:translationXOut="0.16"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_1_3"app:layout_heightPercent="8%"app:layout_marginLeftPercent="46%"app:layout_marginTopPercent="43%"app:layout_widthPercent="15%"/><ImageView
        android:id="@+id/ivFourthImage"app:translationXIn="0.2"app:translationXOut="0.2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_1_4"app:layout_heightPercent="10%"app:layout_marginLeftPercent="44%"app:layout_marginTopPercent="52%"app:layout_widthPercent="13%"/><ImageView
        app:translationXIn="0.06"app:translationXOut="0.06"android:id="@+id/ivSixthImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_1_6"app:layout_heightPercent="7%"app:layout_marginLeftPercent="20%"app:layout_marginTopPercent="47%"app:layout_widthPercent="20%"/><ImageView
        app:translationXIn="0.18"app:translationXOut="0.18"android:id="@+id/ivSeventhImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_1_7"app:layout_heightPercent="8%"app:layout_marginLeftPercent="22%"app:layout_marginTopPercent="35%"app:layout_widthPercent="17%"/><ImageView
        app:translationXIn="0.28"app:translationXOut="0.28"android:id="@+id/ivFifthImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:src="@mipmap/s_1_5"app:layout_heightPercent="10%"app:layout_marginTopPercent="33%"app:layout_widthPercent="15%"/><ImageView
        app:translationXIn="0.14"app:translationXOut="0.14"android:id="@+id/ivEighthImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:src="@mipmap/s_1_8"app:layout_heightPercent="10%"app:layout_marginTopPercent="22%"app:layout_widthPercent="25%"/><TextView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:gravity="center"android:text="@string/text_web_dev"android:textColor="@android:color/white"android:textSize="@dimen/text_size_large"app:layout_heightPercent="15%"app:layout_marginBottomPercent="11%"app:layout_widthPercent="45%"/>
</android.support.percent.PercentRelativeLayout>
  • fragment_page_third
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout
    android:id="@+id/rootThirdPage"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:layout_width="match_parent"android:layout_height="match_parent"tools:ignore="ContentDescription"tools:background="@android:color/holo_blue_dark"><ImageView
        android:id="@+id/ivThirdImage"app:translationXIn="0.4"app:translationXOut="0.4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_2_3"app:layout_heightPercent="40%"app:layout_marginTopPercent="27%"app:layout_widthPercent="100%"/><ImageView
        android:id="@+id/ivSecondImage"app:translationXIn="0.12"app:translationXOut="0.12"android:layout_width="wrap_content"android:layout_height="wrap_content"android:alpha=".5"android:src="@mipmap/s_2_2"app:layout_heightPercent="27%"app:layout_marginLeftPercent="20%"app:layout_marginRightPercent="12%"app:layout_marginTopPercent="20%"app:layout_widthPercent="75%"/><ImageView
        android:id="@+id/ivFirstImage"app:translationXIn="0.16"app:translationXOut="0.16"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@mipmap/s_2_1"app:layout_heightPercent="18%"app:layout_widthPercent="55%"/><ImageView
        android:id="@+id/ivFourthImage"app:translationXIn="0.2"app:translationXOut="0.2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_2_4"app:layout_heightPercent="7%"app:layout_marginLeftPercent="33%"app:layout_marginTopPercent="34%"app:layout_widthPercent="16%"/><ImageView
        android:id="@+id/ivSixthImage"app:translationXIn="0.06"app:translationXOut="0.06"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_2_6"app:layout_heightPercent="7%"app:layout_marginLeftPercent="57%"app:layout_marginTopPercent="29%"app:layout_widthPercent="14%"/><ImageView
        android:id="@+id/ivSeventhImage"app:translationXIn="0.18"app:translationXOut="0.18"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_2_7"app:layout_heightPercent="15%"app:layout_marginLeftPercent="65%"app:layout_marginTopPercent="47%"app:layout_widthPercent="25%"/><ImageView
        android:id="@+id/ivFifthImage"app:translationXIn="0.28"app:translationXOut="0.28"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/s_2_5"app:layout_heightPercent="10%"app:layout_marginLeftPercent="77%"app:layout_marginTopPercent="30%"app:layout_widthPercent="15%"/><TextView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:gravity="center"android:text="@string/text_e_commerce"android:textColor="@android:color/white"android:textSize="@dimen/text_size_large"app:layout_heightPercent="15%"app:layout_marginBottomPercent="11%"app:layout_widthPercent="45%"/>
</android.support.percent.PercentRelativeLayout>
  • activity_main
<?xml version="1.0" encoding="utf-8"?>
<com.hbwj.a19_.animation.ParallaxViewPager 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/parallax_vp"android:layout_width="match_parent"android:background="@android:color/holo_orange_dark"android:layout_height="match_parent"tools:context=".MainActivity"/>

ParallaxViewPager:自定义viewPager

public class ParallaxViewPager extends ViewPager {private List<ParallaxFragment> mFragments;public ParallaxViewPager(Context context) {this(context, null);}public ParallaxViewPager(Context context, AttributeSet attrs) {super(context, attrs);mFragments = new ArrayList<>();}public void setLayout(FragmentManager fm, int[] layoutIds) {mFragments.clear();for (int layoutId : layoutIds) {ParallaxFragment fragment = new ParallaxFragment();Bundle bundle = new Bundle();bundle.putInt(fragment.LAYOUT_ID_KEY, layoutId);fragment.setArguments(bundle);mFragments.add(fragment);}// 设置我们的 ViewPager 的AdaptersetAdapter(new ParallaxPagerAdapter(fm));//设置事件addOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {// 滚动  position 当前位置    positionOffset 0-1     positionOffsetPixels 0-屏幕的宽度pxLog.e("TAG", "position->" + position + " positionOffset->" + positionOffset + " positionOffsetPixels->" + positionOffsetPixels);//获得属性//左边出去,右边进来ParallaxFragment outFragment = mFragments.get(position);List<View> parallaxViews = outFragment.getParallaxViews();for (View parallaxView : parallaxViews) {ParallaxTag tag = (ParallaxTag) parallaxView.getTag(R.id.parallax_tag);parallaxView.setTranslationX(-positionOffsetPixels * tag.translationXOut);parallaxView.setTranslationY(-positionOffsetPixels * tag.translationYOut);}try {//从右边进来ParallaxFragment inFramgent = mFragments.get(position + 1);List<View> inParallaxViews = inFramgent.getParallaxViews();for (View parallaxView : inParallaxViews) {ParallaxTag tag = (ParallaxTag) parallaxView.getTag(R.id.parallax_tag);parallaxView.setTranslationX((getMeasuredWidth() - positionOffsetPixels) * tag.translationXIn);parallaxView.setTranslationY((getMeasuredWidth() - positionOffsetPixels) * tag.translationYIn);}} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onPageSelected(int position) {//页面切换完毕}@Overridepublic void onPageScrollStateChanged(int state) {}});}private class ParallaxPagerAdapter extends FragmentPagerAdapter {public ParallaxPagerAdapter(FragmentManager fm) {super(fm);}@Overridepublic Fragment getItem(int position) {return mFragments.get(position);}@Overridepublic int getCount() {return mFragments.size();}}}

ParallaxFragment:View拦截解析属性

public class ParallaxFragment extends Fragment implements LayoutInflaterFactory {public static final String LAYOUT_ID_KEY = "LAYOUT_ID_KEY";private CompatViewInflater mAppCompatViewInflater;private static final boolean IS_PRE_LOLLIPOP = Build.VERSION.SDK_INT < 21;private int[] mParallaxAttrs = new int[]{R.attr.translationXIn,R.attr.translationXOut, R.attr.translationYIn, R.attr.translationYOut};// 存放所有的需要位移的Viewprivate List<View> mParallaxViews = new ArrayList<>();@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {int layoutId = getArguments().getInt(LAYOUT_ID_KEY);// View创建的时候 我们去解析属性  这里传 inflater 有没有问题?// 单例设计模式 代表着所有的View的创建都会是该 Fragment 去创建的inflater = inflater.cloneInContext(getContext());//克隆一个LayoutInflaterCompat.setFactory(inflater, this);return inflater.inflate(layoutId, container, false);}// View都会来这里,创建View// 拦截到View的创建  获取View之后要去解析// 1. 创建View@Overridepublic View onCreateView(View parent, String name, Context context, AttributeSet attrs) {//View都会来这里,创建view// First let the Activity's Factory try and inflate the view// First let the Activity's Factory try and inflate the viewView view = createView(parent, name, context, attrs);if (view != null) {//解析属性analysisAttrs(view,context,attrs);}// If the Factory didn't handle it, let our createView() method tryreturn view;}/*** 解析属性*/private void analysisAttrs(View view, Context context, AttributeSet attrs) {TypedArray array=context.obtainStyledAttributes(attrs,mParallaxAttrs);if(array!=null&&array.getIndexCount()!=0){/*  float xIn =attar.getFloat(0,0f);float xOut  =attar.getFloat(1,0f);float yIn  =attar.getFloat(2,0f);float yOut=attar.getFloat(3,0f);*/int n = array.getIndexCount();ParallaxTag tag=new ParallaxTag();for (int i = 0; i < n; i++) {int attr = array.getIndex(i);switch (attr) {case 0:tag.translationXIn = array.getFloat(attr,0f);break;case 1:tag.translationXOut = array.getFloat(attr,0f);break;case 2:tag.translationYIn = array.getFloat(attr,0f);break;case 3:tag.translationYOut = array.getFloat(attr,0f);break;}}//保存自定义viewview.setTag(R.id.parallax_tag,tag);//Log.e("TAG",tag.toString());mParallaxViews.add(view);}array.recycle();}public View createView(View parent, final String name, @NonNull Context context,@NonNull AttributeSet attrs) {if (mAppCompatViewInflater == null) {mAppCompatViewInflater = new CompatViewInflater();}boolean inheritContext = (attrs instanceof XmlPullParser)// If we have a XmlPullParser, we can detect where we are in the layout? ((XmlPullParser) attrs).getDepth() > 1// Otherwise we have to use the old heuristic: shouldInheritContext((ViewParent) parent);return mAppCompatViewInflater.createView(parent, name, context, attrs, inheritContext,IS_PRE_LOLLIPOP, /* Only read android:theme pre-L (L+ handles this anyway) */true, /* Read read app:theme as a fallback at all times for legacy reasons */VectorEnabledTintResources.shouldBeUsed() /* Only tint wrap the context if enabled */);}private boolean shouldInheritContext(ViewParent parent) {if (parent == null) {// The initial parent is null so just return falsereturn 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 (!(parent instanceof View)|| 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();}}//获得所有属性public List<View> getParallaxViews() {return mParallaxViews;}
}

CompatViewInflater:参考系统源码

public class CompatViewInflater {private static final Class<?>[] sConstructorSignature = new Class[]{Context.class, AttributeSet.class};private static final String LOG_TAG = "AppCompatViewInflater";private final Object[] mConstructorArgs = new Object[2];private static final Map<String, Constructor<? extends View>> sConstructorMap= new ArrayMap<>();private static final int[] sOnClickAttrs = new int[]{android.R.attr.onClick};public final View createView(View parent, final String name, @NonNull Context context,@NonNull AttributeSet attrs, boolean inheritContext,boolean readAndroidTheme, boolean readAppTheme, boolean wrapContext) {final Context originalContext = context;// We can emulate Lollipop's android:theme attribute propagating down the view hierarchy// by using the parent's contextif (inheritContext && parent != null) {context = parent.getContext();}if (readAndroidTheme || readAppTheme) {// We then apply the theme on the context, if specifiedcontext = themifyContext(context, attrs, readAndroidTheme, readAppTheme);}if (wrapContext) {context = TintContextWrapper.wrap(context);}View view = null;// We need to 'inject' our tint aware Views in place of the standard framework versionsswitch (name) {case "TextView":view = new AppCompatTextView(context, attrs);break;case "ImageView":view = new AppCompatImageView(context, attrs);break;case "Button":view = new AppCompatButton(context, attrs);break;case "EditText":view = new AppCompatEditText(context, attrs);break;case "Spinner":view = new AppCompatSpinner(context, attrs);break;case "ImageButton":view = new AppCompatImageButton(context, attrs);break;case "CheckBox":view = new AppCompatCheckBox(context, attrs);break;case "RadioButton":view = new AppCompatRadioButton(context, attrs);break;case "CheckedTextView":view = new AppCompatCheckedTextView(context, attrs);break;case "AutoCompleteTextView":view = new AppCompatAutoCompleteTextView(context, attrs);break;case "MultiAutoCompleteTextView":view = new AppCompatMultiAutoCompleteTextView(context, attrs);break;case "RatingBar":view = new AppCompatRatingBar(context, attrs);break;case "SeekBar":view = new AppCompatSeekBar(context, attrs);break;}if (view == null && originalContext != context) {// If the original context does not equal our themed context, then we need to manually// inflate it using the name so that android:theme takes effect.view = createViewFromTag(context, name, attrs);}if (view != null) {// If we have created a view, check it's android:onClickcheckOnClickListener(view, attrs);}return view;}private static Context themifyContext(Context context, AttributeSet attrs,boolean useAndroidTheme, boolean useAppTheme) {final TypedArray a = context.obtainStyledAttributes(attrs, android.support.v7.appcompat.R.styleable.View, 0, 0);int themeId = 0;if (useAndroidTheme) {// First try reading android:theme if enabledthemeId = a.getResourceId(android.support.v7.appcompat.R.styleable.View_android_theme, 0);}if (useAppTheme && themeId == 0) {// ...if that didn't work, try reading app:theme (for legacy reasons) if enabledthemeId = a.getResourceId(android.support.v7.appcompat.R.styleable.View_theme, 0);if (themeId != 0) {Log.i(LOG_TAG, "app:theme is now deprecated. "+ "Please move to using android:theme instead.");}}a.recycle();if (themeId != 0 && (!(context instanceof ContextThemeWrapper)|| ((ContextThemeWrapper) context).getThemeResId() != themeId)) {// If the context isn't a ContextThemeWrapper, or it is but does not have// the same theme as we need, wrap it in a new wrappercontext = new ContextThemeWrapper(context, themeId);}return context;}private View createViewFromTag(Context context, String name, AttributeSet attrs) {if (name.equals("view")) {name = attrs.getAttributeValue(null, "class");}try {mConstructorArgs[0] = context;mConstructorArgs[1] = attrs;if (-1 == name.indexOf('.')) {// try the android.widget prefix first...return createView(context, name, "android.widget.");} else {return createView(context, name, null);}} catch (Exception e) {// We do not want to catch these, lets return null and let the actual LayoutInflater// tryreturn null;} finally {// Don't retain references on context.mConstructorArgs[0] = null;mConstructorArgs[1] = null;}}private void checkOnClickListener(View view, AttributeSet attrs) {final Context context = view.getContext();if (!(context instanceof ContextWrapper) ||(Build.VERSION.SDK_INT >= 15 && !ViewCompat.hasOnClickListeners(view))) {// Skip our compat functionality if: the Context isn't a ContextWrapper, or// the view doesn't have an OnClickListener (we can only rely on this on API 15+ so// always use our compat code on older devices)return;}final TypedArray a = context.obtainStyledAttributes(attrs, sOnClickAttrs);final String handlerName = a.getString(0);if (handlerName != null) {view.setOnClickListener(new DeclaredOnClickListener(view, handlerName));}a.recycle();}private View createView(Context context, String name, String prefix)throws ClassNotFoundException, InflateException {Constructor<? extends View> constructor = sConstructorMap.get(name);try {if (constructor == null) {// Class not found in the cache, see if it's real, and try to add itClass<? extends View> clazz = context.getClassLoader().loadClass(prefix != null ? (prefix + name) : name).asSubclass(View.class);constructor = clazz.getConstructor(sConstructorSignature);sConstructorMap.put(name, constructor);}constructor.setAccessible(true);return constructor.newInstance(mConstructorArgs);} catch (Exception e) {// We do not want to catch these, lets return null and let the actual LayoutInflater// tryreturn null;}}private static class DeclaredOnClickListener implements View.OnClickListener {private final View mHostView;private final String mMethodName;private Method mResolvedMethod;private Context mResolvedContext;public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {mHostView = hostView;mMethodName = methodName;}@Overridepublic void onClick(@NonNull View v) {if (mResolvedMethod == null) {resolveMethod(mHostView.getContext(), mMethodName);}try {mResolvedMethod.invoke(mResolvedContext, v);} catch (IllegalAccessException e) {throw new IllegalStateException("Could not execute non-public method for android:onClick", e);} catch (InvocationTargetException e) {throw new IllegalStateException("Could not execute method for android:onClick", e);}}@NonNullprivate void resolveMethod(@Nullable Context context, @NonNull String name) {while (context != null) {try {if (!context.isRestricted()) {final Method method = context.getClass().getMethod(mMethodName, View.class);if (method != null) {mResolvedMethod = method;mResolvedContext = context;return;}}} catch (NoSuchMethodException e) {// Failed to find method, keep searching up the hierarchy.}if (context instanceof ContextWrapper) {context = ((ContextWrapper) context).getBaseContext();} else {// Can't search up the hierarchy, null out and fail.context = null;}}final int id = mHostView.getId();final String idText = id == View.NO_ID ? "" : " with id '"+ mHostView.getContext().getResources().getResourceEntryName(id) + "'";throw new IllegalStateException("Could not find method " + mMethodName+ "(View) in a parent or ancestor Context for android:onClick "+ "attribute defined on view " + mHostView.getClass() + idText);}}
}

ParallaxTag:

public class ParallaxTag {public float translationXIn;public float translationXOut;public float translationYIn;public float translationYOut;@Overridepublic String toString() {return "translationXIn->"+translationXIn+" translationXOut->"+translationXOut+" translationYIn->"+translationYIn+" translationYOut->"+translationYOut;}
}

自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources><!-- X方向上的位移 --><attr name="translationXIn" format="float" /><attr name="translationXOut" format="float" /><!-- Y方向上的位移 --><attr name="translationYIn" format="float" /><attr name="translationYOut" format="float" />
</resources>

自定义view-视察动画之酷狗音乐引导页相关推荐

  1. 视差动画 - 酷狗音乐引导页

    下面来看一个效果: 完整代码如下: public class MainActivity extends AppCompatActivity {private ParallaxViewPager vp; ...

  2. Android插件化开发指南——实践之Activity转场效果(仿酷狗音乐启动页)

    文章目录 1. 前言 2. Activity退出动画 2.1 简单使用 2.2 overridePendingTransition 3. 后记 1. 前言 在Android插件化开发指南--2.15 ...

  3. Android插件化开发指南——实践之仿酷狗音乐首页

    文章目录 1. 前言 2. 布局分析 3. 底部导航栏的实现 4. 顶部导航栏和ViewPager+Fragment的关联 1. 前言 在Android插件化开发指南--2.15 实现一个音乐播放器A ...

  4. 自定义View - 仿酷狗音乐主页面侧滑效果

    作者:Delusion 概述 最近在用酷狗音乐时发现酷狗音乐的主页侧滑效果不错,忍不住手痒痒,就想实现一下看看 效果分析 我们可以看出分为两个部分 (菜单页面.主题页面)所以这里采用自定义ViewGr ...

  5. Android插件化开发指南——实践之仿酷狗音乐首页(自定义ImageView控件)

    文章目录 1. 前言 2. 基础环境--实现RecyclerView的网格布局 3. 自定义ImageView 3. 后记 1. 前言 拟定实现效果部分为下图的歌单列表部分,也就是图中红线框出来的部分 ...

  6. IOS基础之仿酷狗音乐第1天

    IOS基础之仿酷狗音乐第1天 细节较多,涉及字典转模型,tableView 的使用,模态框,自定义模态,音视频播放,全局PCH文件,xib加载,自定义 xib ,info.plist文件的加载,动画的 ...

  7. java仿酷狗音乐源码_【附项目源码】仿酷狗音乐客户端,浅淡动感歌词补充

    原标题:[附项目源码]仿酷狗音乐客户端,浅淡动感歌词补充 1.前言 之前写了几篇关于动感歌词的简单介绍,相信大家还有印象,这里就不多说了,这篇要说的是,关于翻译歌词和音译歌词,以及我在解析和显示这两种 ...

  8. 实现 酷狗音乐 歌词播放效果

    今天将为大家带来 粗略版 酷狗音乐 歌词播放的效果.我们一步一步来.首先做这个是因为有一次公司项目中需要做一个汽车扫描效果的时候,想到来做这个歌词播放效果的.那么我们这次先上效果图: 好的上面的文字是 ...

  9. 仿酷狗音乐播放器已开源!

    转载请说明原出处,谢谢:http://blog.csdn.net/zhuhongshu/article/details/41037875 距离我发布测试版的Redrain音乐盒(仿酷狗播放器),现在正 ...

最新文章

  1. 透视 CES 2018:不容错过的四大科技趋势
  2. Git和Github简单教程
  3. CentOS安装和配置FTP
  4. 【Tiny4412】EMMC启动最小网络文件系统
  5. maven的常见问题_Maven常见问题和陷阱
  6. linux c c 常用的日志库,mslog: 一款超轻量级的C日志库,无需依赖额外的库,测试或移植过的系统有Linux(ubuntu,centos),Windows以及部分嵌入式设备;...
  7. 华为手机助手 for Mac(华为手机管理软件)中文版
  8. fmea第五版pfmea表格_FMEA第五版中文版.pdf
  9. addEventListener与attachEvent
  10. 光学计算机的工作原理,使用光学计算机的人工智能超分辨率
  11. iir数字滤波器设计及matlab实现,终稿毕业论文:IIR数字滤波器设计及其MATLAB实现.docOK版(样例3)...
  12. html可以转换wps嘛,如何将图文并茂的网页快速转换为WPS或word文档
  13. 计算机自动关机原理,电脑自动关机什么原因 电脑自动关机是怎么回事
  14. 穆易天气app代码(二)
  15. 收藏了800道Java后端经典面试题,共享给大家
  16. 服务器集群有哪些类型
  17. 自定义NavigationBar的思路
  18. 质量检验中那些不为人所知的事儿
  19. 要把服务器架在太空的海盗湾,为什么能活十五年?
  20. 艾艾贴关于Spring Cloud大型互联网分布式企业微服务云架构

热门文章

  1. 18 linux mint 驱动_Linux Mint 18.2双显卡之安装NVIDIA官方闭源驱动
  2. (数据分析)第02章 Python语法基础,IPython和Jupyter Notebooks.md
  3. MATLAB算法实战应用案例精讲-【智能优化算法】哈里斯鹰(HHO)(附matlab代码实现)
  4. 联想台式一体机win10重装win7系统
  5. echart时日周分别统计
  6. 用户贷款风险预测——Error in matrix(unlist(value, recursive = FALSE, use.names = FALSE), nrow = nr, : length
  7. ggplot2学习笔记5:工具箱(一)基础图层、标签、注释、群组几何对象、曲面图
  8. 大型企业建设财务共享中心需要重视的5个核心要素
  9. 动态解析AIS原始数据
  10. 【sentinel】流控规则详解