From ea4c6a7c1d889044a48e644e4a368c0637174c6d Mon Sep 17 00:00:00 2001 From: CSnowStack Date: Thu, 27 Apr 2017 10:39:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=BFairbnb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 5 +- .idea/qaplug_profiles.xml | 289 ++++++++++++++++ README.md | 157 +-------- app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 3 +- .../main/java/cq/airbnb/AirbnbActivity.java | 79 +++++ app/src/main/java/cq/airbnb/BGBehavior.java | 33 ++ app/src/main/java/cq/airbnb/ListBehavior.java | 59 ++++ .../java/cq/airbnb/SearchAllBehavior.java | 88 +++++ .../java/cq/airbnb/SearchItemBehavior.java | 136 ++++++++ app/src/main/java/cq/airbnb/TabBehavior.java | 326 ++++++++++++++++++ .../main/java/cq/airbnb/UpIconBehavior.java | 63 ++++ .../java/cq/behaviordemo/ItemFragment.java | 46 +-- .../cq/behaviordemo/adapter/ItemAdapter.java | 14 +- .../behavior/HeaderScrollingViewBehavior.java | 4 +- .../behaviordemo/behavior/ListBehavior.java | 6 +- .../ic_trips_search_anywhere.png | Bin 0 -> 2261 bytes .../ic_trips_search_calendar.png | Bin 0 -> 1008 bytes .../drawable-xhdpi/ic_trips_search_guest.png | Bin 0 -> 1158 bytes .../ic_trips_search_view_up_chevron.png | Bin 0 -> 305 bytes app/src/main/res/drawable-xhdpi/search.png | Bin 0 -> 2379 bytes .../main/res/drawable/bg_airbnb_condition.xml | 5 + .../res/drawable/bg_airbnb_condition_gray.xml | 5 + app/src/main/res/drawable/bg_tab.xml | 10 + app/src/main/res/drawable/bg_tab_white.xml | 10 + app/src/main/res/drawable/divider_padding.xml | 4 + app/src/main/res/layout/activity_airbnb.xml | 176 ++++++++++ app/src/main/res/layout/activity_iread.xml | 13 + app/src/main/res/layout/fragment_item.xml | 1 + app/src/main/res/values/colors.xml | 5 + app/src/main/res/values/dimens.xml | 18 + app/src/main/res/values/styles.xml | 14 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 0 gradlew.bat | 180 +++++----- img/Behavior.apk | Bin 2079010 -> 0 bytes img/c.gif | Bin 1585733 -> 0 bytes img/close.gif | Bin 669555 -> 0 bytes img/open.gif | Bin 659455 -> 0 bytes img/preview.gif | Bin 6130077 -> 1522007 bytes 41 files changed, 1458 insertions(+), 299 deletions(-) create mode 100644 .idea/qaplug_profiles.xml create mode 100644 app/src/main/java/cq/airbnb/AirbnbActivity.java create mode 100644 app/src/main/java/cq/airbnb/BGBehavior.java create mode 100644 app/src/main/java/cq/airbnb/ListBehavior.java create mode 100644 app/src/main/java/cq/airbnb/SearchAllBehavior.java create mode 100644 app/src/main/java/cq/airbnb/SearchItemBehavior.java create mode 100644 app/src/main/java/cq/airbnb/TabBehavior.java create mode 100644 app/src/main/java/cq/airbnb/UpIconBehavior.java create mode 100644 app/src/main/res/drawable-xhdpi/ic_trips_search_anywhere.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_trips_search_calendar.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_trips_search_guest.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_trips_search_view_up_chevron.png create mode 100644 app/src/main/res/drawable-xhdpi/search.png create mode 100644 app/src/main/res/drawable/bg_airbnb_condition.xml create mode 100644 app/src/main/res/drawable/bg_airbnb_condition_gray.xml create mode 100644 app/src/main/res/drawable/bg_tab.xml create mode 100644 app/src/main/res/drawable/bg_tab_white.xml create mode 100644 app/src/main/res/drawable/divider_padding.xml create mode 100644 app/src/main/res/layout/activity_airbnb.xml create mode 100644 app/src/main/res/layout/activity_iread.xml mode change 100644 => 100755 gradlew delete mode 100644 img/Behavior.apk delete mode 100644 img/c.gif delete mode 100644 img/close.gif delete mode 100644 img/open.gif diff --git a/.idea/misc.xml b/.idea/misc.xml index cca2cda..ce92608 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,12 +37,15 @@ - + + + diff --git a/.idea/qaplug_profiles.xml b/.idea/qaplug_profiles.xml new file mode 100644 index 0000000..e24d63d --- /dev/null +++ b/.idea/qaplug_profiles.xml @@ -0,0 +1,289 @@ + + + + + \ No newline at end of file diff --git a/README.md b/README.md index f838458..2c2233c 100644 --- a/README.md +++ b/README.md @@ -4,169 +4,14 @@ [项目地址](https://github.com/CSnowStack/BehaviorDemo) -[下载体验](https://github.com/CSnowStack/BehaviorDemo/blob/master/img/Behavior.apk) #### 建议 请先阅读[这篇文章](http://www.jianshu.com/p/f7989a2a3ec2) > 好多东西抄自这里 -#### 效果来源 - -[这里是地址](https://material.uplabs.com/posts/profile-4f03fc6b-1a82-42ab-8a3e-f50dcbc10253) - - -![原图](https://github.com/CSnowStack/BehaviorDemo/blob/master/img/preview.gif) #### 我的实现 -![实现的效果](https://github.com/CSnowStack/BehaviorDemo/blob/master/img/c.gif) - - - - -> 一些细节没有实现 ,见谅,录制的gif效果也不太好 :-( - - -### 实现 - -#### 依赖关系 - `Tab` 监听 `onNestedPreScroll`来进行滑动,`Toolbar` 依赖 `FytContent`,其余的依赖 `Tab` - -#### 变化 -- `Tab` 的移动是手指滑动距离的 1/2 ,会根据停下来的位置判断是应该回到原位置还是下一个状态并进行移动 - -- `VP` 跟随 `Tab`, `HeaderScrollingViewBehavior`什么的请看建议,移动则没什么难度 - -- `BGContent` 跟随 `Tab`,根据`Tab`运动的比例,缩放,移动,修改 里面`View`的`Alpha` - -- `BG` 跟随 `Tab`,首先向下移动到 `BGContent` 的高度的 1/2的地方 - -- `Editor` 跟随 `Tab`,首先移动到 `BGContent`下面加上预留的`Padding`,随着比例移动并设置alpha - -- `Icon` 跟随 `Tab`,根据`Tab`运动的比例进行移动和调整大小 - -- `Name` 同上 - -- `Socre` 同上,没有缩放 - - -- `ToolBarIcon` 跟随`BGContent` ,根据`BGContent`移动的比例修改图标的`Alpha` - -#### 部分代码 - -```java -//TabBehavior -public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { - super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); - mUp = dy > 0; - if(isChildRequestScroll(child.getTranslationY())){//如果list需要滑动这边就不动 - consumed[1]=0; - return; - } - consumed[1]=dy;//全部消耗 - int distance = -dy / 2;//降低移动的速度 - - - if (child.getTranslationY() + distance < -mMaxDistance) { - distance = -mMaxDistance; - } else if (child.getTranslationY() + distance > 0) { - distance = 0; - } else { - distance = (int) (child.getTranslationY() + distance); - } - child.setTranslationY(distance); -} - -/** - * Child是否需要滑动 - */ -private boolean isChildRequestScroll(float translationY) { - return (translationY == -mMaxDistance &&//在顶部 - mViewPager.getAdapter() != null && //有适配器 - mViewPager.getAdapter().getCount() > 0 &&//有item - mViewPager.getAdapter() instanceof IsChildRequestScrollListener && //实现了 - ((IsChildRequestScrollListener) mViewPager.getAdapter()).requestScroll(mUp)//需要滑动 - ); -} - - -//设置 listener 检测是否需要展开 -@Override -public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { - mControlChange=true; - - if(mViewPager.getAdapter() != null && //有适配器 - mViewPager.getAdapter().getCount() > 0 &&//有item - mViewPager.getAdapter() instanceof SupportNeedExpendListener&& - ((SupportNeedExpendListener) mViewPager.getAdapter()).getNeedExpendListener()==null){ - ((SupportNeedExpendListener) mViewPager.getAdapter()).setNeedExpendListener(this); - } - return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; -} - -/** - * list fling到头的时候 展开 - */ - @Override - public void needExpand() { - if(!mControlChange){ - mValueAnimator.setDuration(500); - mValueAnimator.removeAllUpdateListeners(); - mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mTab.setTranslationY((animation.getAnimatedFraction()-1)*mMaxDistance); - } - }); - mValueAnimator.start(); - } - } - - /** - * 开启硬件离屏缓存,放入不服导致缓存失效的 view - * 效果都还好 - */ - if(mHardwareViews.size()==0){ - mHardwareViews.add(parent.findViewById(R.id.txt_name)); - mHardwareViews.add(parent.findViewById(R.id.img_icon)); - mHardwareViews.add(parent.findViewById(R.id.lyt_score)); - mHardwareViews.add(parent.findViewById(R.id.tab_layout)); - mHardwareViews.add(parent.findViewById(R.id.bg)); - mHardwareViews.add(parent.findViewById(R.id.lyt_editor)); - mHardwareViews.add(parent.findViewById(R.id.lyt_statistics)); - - //开启硬件离屏缓存 - mValueAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - for(View v:mHardwareViews){ - v.setLayerType(View.LAYER_TYPE_NONE,null); - } - } - - @Override - public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); - for(View v:mHardwareViews){ - v.setLayerType(View.LAYER_TYPE_HARDWARE,null); - } - } - }); - } - - -``` - ->代码是蛮简单的 ,直接看项目即可,就那几行代码, 又加了点功能 耦合度变高了的感觉欢迎 Star,提 issue 还有PR - - -##### 开启硬件离屏缓存 -![开启硬件离屏缓存](https://github.com/CSnowStack/BehaviorDemo/blob/master/img/open.gif) - -##### 关闭硬件离屏缓存 -![关闭硬件离屏缓存](https://github.com/CSnowStack/BehaviorDemo/blob/master/img/close.gif) +![实现的效果](https://github.com/CSnowStack/BehaviorDemo/blob/master/img/preview.gif.gif) -### TODO -- ~~在向上fling的过程中,向下滑,会出现错乱的情况 :-(~~ diff --git a/app/build.gradle b/app/build.gradle index 842d9c9..fa024a7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,4 +26,6 @@ dependencies { compile "com.android.support:recyclerview-v7:$android_support_version" compile "com.android.support:cardview-v7:$android_support_version" compile 'de.hdodenhof:circleimageview:2.1.0' + compile 'com.android.support.constraint:constraint-layout:1.0.2' + } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d880ed5..fd0dbd4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,7 +8,8 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + diff --git a/app/src/main/java/cq/airbnb/AirbnbActivity.java b/app/src/main/java/cq/airbnb/AirbnbActivity.java new file mode 100644 index 0000000..8f43bab --- /dev/null +++ b/app/src/main/java/cq/airbnb/AirbnbActivity.java @@ -0,0 +1,79 @@ +package cq.airbnb; + +import android.os.Bundle; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.TabLayout; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.LinearLayout; + +import cq.behaviordemo.R; +import cq.behaviordemo.adapter.ItemAdapter; + +/** + * 仿爱彼迎主页 + */ + +public class AirbnbActivity extends AppCompatActivity { + private TabLayout mTabLayout; + private ViewPager mViewPager; + private LinearLayout mLytUP; + private LinearLayout mLytAll; + + @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_airbnb); + findView(); + initView(); + initEvent(); + mTabLayout.setTranslationY(getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_min)); + } + + private void findView() { + mTabLayout = (TabLayout) findViewById(R.id.tab_layout); + mViewPager = (ViewPager) findViewById(R.id.viewpager); + mLytUP = (LinearLayout) findViewById(R.id.lyt_up); + mLytAll = (LinearLayout) findViewById(R.id.lyt_all); + + mLytUP.setOnClickListener(new View.OnClickListener() { + @Override public void onClick(View v) { + ((TabBehavior) ((CoordinatorLayout.LayoutParams) mTabLayout.getLayoutParams()).getBehavior()).hideItem(); + + } + }); + mLytAll.setOnClickListener(new View.OnClickListener() { + @Override public void onClick(View v) { + ((TabBehavior) ((CoordinatorLayout.LayoutParams) mTabLayout.getLayoutParams()).getBehavior()).needExpand(); + + } + }); + } + + private void initView() { + mViewPager.setAdapter(new ItemAdapter(getSupportFragmentManager(), mViewPager, 2)); + mTabLayout.setupWithViewPager(mViewPager); + } + + private void initEvent() { + mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { + mViewPager.setCurrentItem(tab.getPosition()); + } + + @Override + public void onTabUnselected(TabLayout.Tab tab) { + + } + + @Override + public void onTabReselected(TabLayout.Tab tab) { + + } + }); + + } + + +} diff --git a/app/src/main/java/cq/airbnb/BGBehavior.java b/app/src/main/java/cq/airbnb/BGBehavior.java new file mode 100644 index 0000000..c5c3de7 --- /dev/null +++ b/app/src/main/java/cq/airbnb/BGBehavior.java @@ -0,0 +1,33 @@ +package cq.airbnb; + +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.TabLayout; +import android.util.AttributeSet; +import android.view.View; + +import cq.behaviordemo.R; + +/** + * 背景的behavior + */ + +public class BGBehavior extends CoordinatorLayout.Behavior { + + private int mTranslationMax; + public BGBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + mTranslationMax=context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_max); + } + + + @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { + return dependency instanceof TabLayout; + } + + @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { + child.setTranslationY(dependency.getTranslationY()-mTranslationMax); + + return true; + } +} diff --git a/app/src/main/java/cq/airbnb/ListBehavior.java b/app/src/main/java/cq/airbnb/ListBehavior.java new file mode 100644 index 0000000..669f0f6 --- /dev/null +++ b/app/src/main/java/cq/airbnb/ListBehavior.java @@ -0,0 +1,59 @@ +package cq.airbnb; + +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.TabLayout; +import android.util.AttributeSet; +import android.view.View; + +import java.util.List; + +import cq.behaviordemo.R; +import cq.behaviordemo.behavior.HeaderScrollingViewBehavior; + +/** + * 控制列表的移动 + */ + +public class ListBehavior extends HeaderScrollingViewBehavior { + private int mHeightToolbar; + public ListBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + mHeightToolbar=context.getResources().getDimensionPixelOffset(R.dimen.toolbar_height); + } + + + @Override + public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { + return isDependOn(dependency); + } + + + @Override public View findFirstDependency(List views) { + for (View view : views) { + if (isDependOn(view)) + return view; + } + return null; + } + + @Override protected int getScrollRange(View v) { + if (isDependOn(v)) { + return 0; + } else { + return super.getScrollRange(v); + } + } + + private boolean isDependOn(View dependency) { + return dependency instanceof TabLayout; + } + + //跟随tab移动 + @Override + public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { + + child.setTranslationY(dependency.getTranslationY()); + return true; + } +} diff --git a/app/src/main/java/cq/airbnb/SearchAllBehavior.java b/app/src/main/java/cq/airbnb/SearchAllBehavior.java new file mode 100644 index 0000000..7057b24 --- /dev/null +++ b/app/src/main/java/cq/airbnb/SearchAllBehavior.java @@ -0,0 +1,88 @@ +package cq.airbnb; + +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.TabLayout; +import android.util.AttributeSet; +import android.view.View; + +import cq.behaviordemo.R; + +/** + * 搜索所有的behavior + */ + +public class SearchAllBehavior extends CoordinatorLayout.Behavior { + + /** + * 改变行为的高度 + * translationY 由 mTranslationMin mTranslationMin+mChangeHeight + */ + private int mChangeHeight, mTranslationMin, mTranslationMax; + private int mMarginTop; + + /** + * 需要gone的时候移动到屏幕外 + */ + private int mTranslationGone; + + private int mHeightUp; + + public SearchAllBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + mMarginTop = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_padding_content); + mHeightUp = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_up_height); + + mTranslationMin =context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_min); + + mTranslationMax =context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_max); + } + + @Override public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { + parent.onLayoutChild(child, layoutDirection); + mChangeHeight = mHeightUp - mMarginTop; + + + if (mTranslationGone == 0) + mTranslationGone = -child.getRight(); + return true; + } + + /** + * 依赖tabLayout + */ + @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { + return dependency instanceof TabLayout; + } + + @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { + float translationY = dependency.getTranslationY(); + if (translationY < mTranslationMin) {//向上移动的时候跟随tab + if (child.getTranslationX() != 0) { + child.setTranslationX(0); + child.setClickable(true); + } + child.setTranslationY(translationY - mTranslationMin); + } else {//展开的时候,根据比例设置 + //tab 位移的比例 + float fraction = (translationY - mTranslationMin) / (mTranslationMax - mTranslationMin); + //根据比例设置位移的距离 + if (fraction <= 1 / 3f) { + if (child.getTranslationX() != 0) { + child.setTranslationX(0); + } + child.setTranslationY(fraction * mChangeHeight); + child.setAlpha(1 - fraction * 3); + + } else { + if (child.getTranslationX() != mTranslationGone) { + child.setTranslationX(mTranslationGone); + child.setAlpha(0); + } + + } + } + return true; + } +} + diff --git a/app/src/main/java/cq/airbnb/SearchItemBehavior.java b/app/src/main/java/cq/airbnb/SearchItemBehavior.java new file mode 100644 index 0000000..387dc8f --- /dev/null +++ b/app/src/main/java/cq/airbnb/SearchItemBehavior.java @@ -0,0 +1,136 @@ +package cq.airbnb; + +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.TabLayout; +import android.util.AttributeSet; +import android.view.View; + +import cq.behaviordemo.R; + +/** + * 搜索的分类的view的behavior + */ + +public class SearchItemBehavior extends CoordinatorLayout.Behavior { + + /** + * 最大位移距离 mChangeHeight + * translationY 由 mTranslationMin 移动到mTranslationMax + */ + private int mChangeHeight, mTranslationMin, mTranslationMax; + private int mMarginTop; + + /** + * 下面的三个item + */ + private View mItemWhere, mItemWhen, mItemWho; + + /** + * 需要gone的时候移动到屏幕外 + */ + private int mTranslationGone; + private int mHeightUp; + + public SearchItemBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + mMarginTop = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_padding_content); + mHeightUp = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_up_height); + + mTranslationMin =context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_min); + mTranslationMax =context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_max); + } + + @Override public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { + parent.onLayoutChild(child, layoutDirection); + mChangeHeight = mHeightUp - mMarginTop; + + mItemWhere = child.findViewById(R.id.lyt_where); + mItemWhen = child.findViewById(R.id.lyt_when); + mItemWho = child.findViewById(R.id.lyt_who); + + if (mTranslationGone == 0) + mTranslationGone = -child.getRight(); + return true; + } + + /** + * 依赖tabLayout + */ + @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { + return dependency instanceof TabLayout; + } + + @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { + float translationY = dependency.getTranslationY(); + if (translationY >= mTranslationMin) { + if (child.getTranslationX() != 0) { + child.setTranslationX(0); + child.setAlpha(1); + } + + //tab 位移的比例 + float fraction = (translationY - mTranslationMin) / (mTranslationMax - mTranslationMin); + //根据比例设置位移的距离 + child.setTranslationY(fraction * mChangeHeight); + + //根据比例设置透明度 + if (fraction < 1 / 3f) { + if (mItemWhere.getTranslationX() != 0) { + mItemWhere.setTranslationX(0); + } + if (mItemWhen.getTranslationX() != mTranslationGone) { + mItemWhen.setTranslationX(mTranslationGone); + + } + if (mItemWho.getTranslationX() != mTranslationGone) { + mItemWho.setTranslationX(mTranslationGone); + } + + + mItemWhere.setAlpha(fraction * 3); + mItemWhen.setAlpha(0); + mItemWho.setAlpha(0); + } else if (fraction < 2 / 3f) { + if (mItemWhere.getTranslationX() != 0) { + mItemWhere.setTranslationX(0); + } + if (mItemWhen.getTranslationX() != 0) { + mItemWhen.setTranslationX(0); + + } + if (mItemWho.getTranslationX() != mTranslationGone) { + mItemWho.setTranslationX(mTranslationGone); + } + + mItemWhere.setAlpha(1); + mItemWhen.setAlpha(fraction * 3 - 1); + mItemWho.setAlpha(0); + } else { + if (mItemWhere.getTranslationX() != 0) { + mItemWhere.setTranslationX(0); + } + if (mItemWhen.getTranslationX() != 0) { + mItemWhen.setTranslationX(0); + + } + if (mItemWho.getTranslationX() != 0) { + mItemWho.setTranslationX(0); + } + + mItemWhere.setAlpha(1); + mItemWhen.setAlpha(1); + mItemWho.setAlpha(fraction * 3 - 2); + } + } else { + if (child.getTranslationX() != mTranslationGone) { + child.setTranslationX(mTranslationGone); + child.setAlpha(0); + } + + } + return true; + + } +} + diff --git a/app/src/main/java/cq/airbnb/TabBehavior.java b/app/src/main/java/cq/airbnb/TabBehavior.java new file mode 100644 index 0000000..ccfd646 --- /dev/null +++ b/app/src/main/java/cq/airbnb/TabBehavior.java @@ -0,0 +1,326 @@ +package cq.airbnb; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.TabLayout; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import cq.behaviordemo.Constants; +import cq.behaviordemo.R; +import cq.behaviordemo.listener.IsChildRequestScrollListener; +import cq.behaviordemo.listener.NeedExpandListener; +import cq.behaviordemo.listener.SupportNeedExpendListener; + +/** + * 控制tab + */ + +public class TabBehavior extends CoordinatorLayout.Behavior implements NeedExpandListener { + /** + * 向下滑动的最大距离 + */ + private int mTranslationMax; + + /** + * 最小的距离 + */ + private int mTranslationMin; + + private int mHeightChild; + /** + * 向上滑动,还是向下滑动 + */ + private boolean mUp; + /** + * 手指控制的滑动 + */ + private boolean mControlChange; + + /** + * mValueAnimatorStyle 改变样式 + */ + private ValueAnimator mValueAnimator; + private ViewPager mViewPager; + private TabLayout mTab; + + /** + * 标记是否是需要改变样式 + * 1 头部只显示tab的时候 切换一次 + * 2 头部的显示超出 tab和 all的时候切换一次 + */ + private boolean mWhiteStyle = false; + private TextView mTxtAll; + private View mLytContent, mLytAll; + private Context mContext; + private int mWhite = 0xFFFFFFFF; + private int mGreen = 0xFF128488; + + public TabBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + mValueAnimator = ValueAnimator.ofFloat(0, 1); + mContext = context; + mTranslationMax = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_max); + mTranslationMin = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_min); + mHeightChild=context.getResources().getDimensionPixelOffset(R.dimen.tab_height); + + } + + /** + * 移动初始位置到 all 的下面 + */ + @Override public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { + parent.onLayoutChild(child, layoutDirection); + mTab = (TabLayout) child; + mViewPager = (ViewPager) parent.findViewById(R.id.viewpager); + mLytAll = parent.findViewById(R.id.lyt_all); + mTxtAll = (TextView) mLytAll.findViewById(R.id.txt_all); + mLytContent = parent.findViewById(R.id.content); + + return true; + } + + @Override + public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { + mControlChange = true; + + //传个接口,需要展开的时候回调 + PagerAdapter adapter = mViewPager.getAdapter(); + if (adapter != null && //有适配器 + adapter.getCount() > 0 &&//有item + adapter instanceof SupportNeedExpendListener && + ((SupportNeedExpendListener) adapter).getNeedExpendListener() == null) { + ((SupportNeedExpendListener) adapter).setNeedExpendListener(this); + } + return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; + } + + + /** + * @param dy 向上滑大于0 + */ + @Override + public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { + mUp = dy > 0; + if (mValueAnimator.isRunning()) { + mValueAnimator.cancel(); + } + + //如果list需要滑动 且 不是(向上滑&&tab不在顶部) + if (isChildRequestScroll(child.getTranslationY())) { + consumed[1] = 0; + return; + } + + consumed[1] = dy;//全部消耗 + int distance = -dy / 2;//降低移动的速度 + + + if (child.getTranslationY() + distance > mTranslationMax) {//大于最大距离 + distance = mTranslationMax; + } else if (child.getTranslationY() + distance < 0) {//到顶部 + distance = 0; + } else {//正常 + distance = (int) (child.getTranslationY() + distance); + } + + //判断应该显示的样式 + if (mUp && distance < (mTranslationMin - mHeightChild / 2) && !mWhiteStyle) { + setWhiteStyle(); + } else if (!mUp && distance > (mTranslationMin + mHeightChild / 2) && mWhiteStyle) { + setGreenStyle(); + } + child.setTranslationY(distance); + } + + private void setGreenStyle() { + mWhiteStyle=false; + mTab.setTabTextColors(ContextCompat.getColor(mContext, android.R.color.darker_gray), mWhite); + mLytAll.setBackgroundResource(R.drawable.bg_airbnb_condition); + mTxtAll.setTextColor(mWhite); + mTab.setSelectedTabIndicatorColor(mWhite); + + mLytContent.setBackgroundResource(R.color.airbnb_bg); + + } + + private void setWhiteStyle() { + mWhiteStyle=true; + mTab.setTabTextColors(ContextCompat.getColor(mContext, android.R.color.darker_gray), mGreen); + mLytAll.setBackgroundResource(R.drawable.bg_airbnb_condition_gray); + mTxtAll.setTextColor(ContextCompat.getColor(mContext, android.R.color.black)); + mTab.setSelectedTabIndicatorColor(mGreen); + + mLytContent.setBackgroundResource(android.R.color.white); + } + + + @Override + public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) { + mControlChange = false; + float translationY = child.getTranslationY(); + if (Math.abs(translationY) == mTranslationMax || translationY == mTranslationMin || translationY == 0) { + return; + } + + scroll(child, translationY); + + } + + + /** + * list 不需要滑动就拦截.需要就不拦截 + */ + + @Override + public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY) { + if (velocityY < -1000 && child.getTranslationY() == 0) {//向下滑的速度小于负1000 + mControlChange = false; + showSearchAll(); + } + + return !isChildRequestScroll(child.getTranslationY()); + } + + /** + * 三种情况 + * 1 在顶部 + * 2 在all的下面 + * 3 在condition的下面 + */ + private void scroll(final View child, final float translationY) { + final float shouldMoveDistance; + if (translationY < mHeightChild / 2) {//这段去最上面 + shouldMoveDistance = -translationY; + } else if ((translationY > mHeightChild / 2 && translationY < (mTranslationMin + mHeightChild / 2)) || + (mUp && translationY < (mTranslationMax - mHeightChild))) {//回到中间的点 + shouldMoveDistance = mTranslationMin - translationY; + } else {//去最下面 + shouldMoveDistance = mTranslationMax - translationY; + } + + + mValueAnimator.setDuration((long) (Math.abs(shouldMoveDistance) / mTranslationMax * Constants.DURATION_SCROLL)); + mValueAnimator.removeAllUpdateListeners(); + mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + child.setTranslationY(translationY + animation.getAnimatedFraction() * shouldMoveDistance); + } + }); + mValueAnimator.start(); + } + + + /** + * Child是否需要滑动 + */ + private boolean isChildRequestScroll(float translationY) { + PagerAdapter adapter = mViewPager.getAdapter(); + return ((translationY == 0 || (!mUp && translationY == mTranslationMin))/*在顶部,或者向下滑且在初始位置*/ && + adapter != null && //有适配器 + adapter.getCount() > 0 &&//有item + adapter instanceof IsChildRequestScrollListener && //实现了 + ((IsChildRequestScrollListener) adapter).requestScroll(mUp)//需要滑动 + ); + } + + + /** + * 显示搜索全部 + */ + public void showSearchAll() { + if (!mControlChange && mTab.getTranslationY() == -0 && !mValueAnimator.isRunning()) { + mValueAnimator.setDuration(500); + final float startTranslation = mTab.getTranslationY(); + mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mTab.setTranslationY(startTranslation + animation.getAnimatedFraction() * (mTranslationMin - startTranslation)); + } + }); + mValueAnimator.addListener(new AnimatorListenerAdapter() { + @Override public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mTab.setTranslationY(mTranslationMin); + mValueAnimator.removeAllListeners(); + mValueAnimator.removeAllUpdateListeners(); + } + }); + mValueAnimator.start(); + } + } + + /** + * list fling到头的时候 展开 + */ + @Override + public void needExpand() { + if (!mControlChange && mTab.getTranslationY() != mTranslationMax && !mValueAnimator.isRunning()) { + mValueAnimator.setDuration(500); + final float startTranslation = mTab.getTranslationY(); + + mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + int translation = (int) (startTranslation + animation.getAnimatedFraction() * (mTranslationMax - startTranslation)); + mTab.setTranslationY(translation); + if (mWhiteStyle && translation > (mTranslationMin + mHeightChild / 2)) { + mWhiteStyle = false; + setGreenStyle(); + } + + } + }); + mValueAnimator.addListener(new AnimatorListenerAdapter() { + @Override public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mTab.setTranslationY(mTranslationMax); + mValueAnimator.removeAllListeners(); + mValueAnimator.removeAllUpdateListeners(); + } + }); + mValueAnimator.start(); + } + } + + + /** + * 隐藏搜索的详细条件 + */ + public void hideItem() { + if (!mValueAnimator.isRunning()) { + + mValueAnimator.setDuration(500); + mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float translation = mTranslationMin + (1 - animation.getAnimatedFraction()) * (mTranslationMax - mTranslationMin); + mTab.setTranslationY(translation); + } + }); + mValueAnimator.addListener(new AnimatorListenerAdapter() { + @Override public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mTab.setTranslationY(mTranslationMin); + mValueAnimator.removeAllListeners(); + mValueAnimator.removeAllUpdateListeners(); + } + }); + mValueAnimator.start(); + } + } + + @Override public void onDetachedFromLayoutParams() { + super.onDetachedFromLayoutParams(); + mValueAnimator.cancel(); + } +} diff --git a/app/src/main/java/cq/airbnb/UpIconBehavior.java b/app/src/main/java/cq/airbnb/UpIconBehavior.java new file mode 100644 index 0000000..477b1ac --- /dev/null +++ b/app/src/main/java/cq/airbnb/UpIconBehavior.java @@ -0,0 +1,63 @@ +package cq.airbnb; + +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.TabLayout; +import android.util.AttributeSet; +import android.view.View; + +import cq.behaviordemo.R; + +/** + * 向上的图片的 behavior + */ + +public class UpIconBehavior extends CoordinatorLayout.Behavior { + private int mChangeHeight, mTranslationMin, mTranslationMax; + + + /** + * 需要gone的时候移动到屏幕外 + */ + private int mTranslationGone; + + public UpIconBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + mTranslationMin = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_min); + + mTranslationMax = context.getResources().getDimensionPixelOffset(R.dimen.airbnb_translation_max); + } + + @Override public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { + parent.onLayoutChild(child, layoutDirection); + mChangeHeight = child.getHeight() / 4; + if (mTranslationGone == 0) + mTranslationGone = -child.getRight(); + return true; + } + + @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { + return dependency instanceof TabLayout; + } + + @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { + float translationY = dependency.getTranslationY(); + float fraction = (translationY - mTranslationMin) / (mTranslationMax - mTranslationMin); + //根据比例设置位移的距离 + if (fraction >= 1 / 3f) { + if (child.getTranslationX() != 0) { + child.setTranslationX(0); + } + + float fractionItem = (fraction * 3 - 1) / 2; + child.setTranslationY(-(1 - fractionItem) * mChangeHeight); + child.setAlpha(fractionItem); + } else if (child.getTranslationX() != mTranslationGone) { + child.setTranslationX(mTranslationGone); + child.setAlpha(0); + + } + + return true; + } +} diff --git a/app/src/main/java/cq/behaviordemo/ItemFragment.java b/app/src/main/java/cq/behaviordemo/ItemFragment.java index 404d4ff..fbba090 100644 --- a/app/src/main/java/cq/behaviordemo/ItemFragment.java +++ b/app/src/main/java/cq/behaviordemo/ItemFragment.java @@ -3,6 +3,7 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; +import android.support.v4.view.ViewCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -11,17 +12,14 @@ import cq.behaviordemo.adapter.FriendInfoAdapter; import cq.behaviordemo.listener.IsChildRequestScrollListener; -import cq.behaviordemo.listener.NeedExpandListener; -import cq.behaviordemo.listener.SupportNeedExpendListener; /** - * Created by cqll on 2016/9/30. + * 列表Fragment */ -public class ItemFragment extends Fragment implements IsChildRequestScrollListener ,SupportNeedExpendListener{ +public class ItemFragment extends Fragment implements IsChildRequestScrollListener{ private RecyclerView mRecyclerView; - private NeedExpandListener mNeedExpandListener; public static ItemFragment newInstance() { Bundle args = new Bundle(); @@ -42,46 +40,16 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, private void initView() { mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); mRecyclerView.setAdapter(new FriendInfoAdapter()); - mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - if(dy<0&&((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition()==0){ - if(mNeedExpandListener!=null) - mNeedExpandListener.needExpand(); - } - } - }); } @Override public boolean requestScroll(boolean up) { - if(mRecyclerView!=null&& - mRecyclerView.getAdapter()!=null&& - mRecyclerView.getAdapter().getItemCount()>0){ - - boolean isTop=(((LinearLayoutManager)mRecyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition()==0); - return up || !isTop; - } - return false; - - } - + //向上滑动,并且 mRecyclerView 可以上滑动 + return (up && ViewCompat.canScrollVertically(mRecyclerView, 1)) || + //向下滑动,且可以下滑 + (!up && ViewCompat.canScrollVertically(mRecyclerView, -1)); - @Override - public void setNeedExpendListener(NeedExpandListener listener) { - mNeedExpandListener=listener; - } - - @Override - public NeedExpandListener getNeedExpendListener() { - return mNeedExpandListener; } } diff --git a/app/src/main/java/cq/behaviordemo/adapter/ItemAdapter.java b/app/src/main/java/cq/behaviordemo/adapter/ItemAdapter.java index c097060..4af03fe 100644 --- a/app/src/main/java/cq/behaviordemo/adapter/ItemAdapter.java +++ b/app/src/main/java/cq/behaviordemo/adapter/ItemAdapter.java @@ -20,21 +20,31 @@ public class ItemAdapter extends FragmentStatePagerAdapter implements IsChildRequestScrollListener,SupportNeedExpendListener{ private String [] titles={"MEDIA","ABOUT","REVIEWS"}; + private String [] titles_air={"推荐","房源","体验","攻略"}; private WeakReference mViewPager;//也许有点用 private List mFragments; private NeedExpandListener mNeedExpandListener; + + private int mFlag; public ItemAdapter(FragmentManager fm) { this(fm,null); } public ItemAdapter(FragmentManager fm, ViewPager viewPager) { + this(fm,viewPager,1); + } + public ItemAdapter(FragmentManager fm, ViewPager viewPager,int flag) { super(fm); + mFlag=flag; mViewPager = new WeakReference(viewPager); mFragments=new ArrayList(); mFragments.add(ItemFragment.newInstance()); mFragments.add(ItemFragment.newInstance()); mFragments.add(ItemFragment.newInstance()); + if(flag==2){ + mFragments.add(ItemFragment.newInstance()); + } fillListener(); } @@ -45,12 +55,12 @@ public Fragment getItem(int position) { @Override public int getCount() { - return titles.length; + return mFragments.size(); } @Override public CharSequence getPageTitle(int position) { - return titles[position]; + return mFlag==1?titles[position]:titles_air[position]; } diff --git a/app/src/main/java/cq/behaviordemo/behavior/HeaderScrollingViewBehavior.java b/app/src/main/java/cq/behaviordemo/behavior/HeaderScrollingViewBehavior.java index 3cf57eb..ddfb06a 100644 --- a/app/src/main/java/cq/behaviordemo/behavior/HeaderScrollingViewBehavior.java +++ b/app/src/main/java/cq/behaviordemo/behavior/HeaderScrollingViewBehavior.java @@ -125,9 +125,9 @@ private static int resolveGravity(int gravity) { return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity; } - abstract View findFirstDependency(List views); + public abstract View findFirstDependency(List views); - int getScrollRange(View v) { + protected int getScrollRange(View v) { return v.getMeasuredHeight(); } diff --git a/app/src/main/java/cq/behaviordemo/behavior/ListBehavior.java b/app/src/main/java/cq/behaviordemo/behavior/ListBehavior.java index 3926bcd..7349906 100644 --- a/app/src/main/java/cq/behaviordemo/behavior/ListBehavior.java +++ b/app/src/main/java/cq/behaviordemo/behavior/ListBehavior.java @@ -27,8 +27,7 @@ public boolean layoutDependsOn(CoordinatorLayout parent, View child, View depend } - @Override - View findFirstDependency(List views) { + @Override public View findFirstDependency(List views) { for (View view : views) { if (isDependOn(view)) return view; @@ -36,8 +35,7 @@ View findFirstDependency(List views) { return null; } - @Override - int getScrollRange(View v) { + @Override protected int getScrollRange(View v) { if (isDependOn(v)) { return -mHeightToolbar; } else { diff --git a/app/src/main/res/drawable-xhdpi/ic_trips_search_anywhere.png b/app/src/main/res/drawable-xhdpi/ic_trips_search_anywhere.png new file mode 100644 index 0000000000000000000000000000000000000000..01aa6ce8682350dd4f3f2ae42f3ad1ae731d20f7 GIT binary patch literal 2261 zcmeHI`9ISQ0RB3M%zc!}BrggXF;Q=h=9p#7P@8M7CZil-3}IH9D@T`9jvN!R(Xx42 zFDXTG^wLMUHo4}=k%|(%`a9m9&*yob&-3H+{PJYDqn*Gq8ZrO?fRWA!j~%!DMJcfz zE#jsw0)QCce$vxnC;rCo1^%}SuwkFmcgowuc%ZR>lr4odw7}<5tJXK!p5lZ7%@(86 zxdyVZg0+jzD$A{O(y_?ynDQgDyUpE4bcxS=OKR`-z0_7XkI0(5eo~Oc%mV-k2PDGI zlQR7A)Erg=sgfcVb&xKls7E-B86uQH%8|rcc*>^t$C?Ih`f6rbmUd?5v!nyC&GCMr zFJ*9vzEzKXJK!4E%I8h4H$ydLlaI{dQY|iW5f|DRsUIW_xw@N$wm1G&21XlipAE+v z9an3MWa>Ht){rE+1R)6}3@KzjlQf`)bT{-Ku??tS5wTkaf zpufoZ7%I!wS|yzG>g#~WQ({>b8chw;vGr9OYl-+iMpuO?m8rhzP@>V6)hiNZcXjd4 zp-IU~+MW^anTw5n2LbsGF!HSS_P7wE)w$G4>UR;yVJg2W1(#cAi<$-_wUPHi^(b)VVA}-Ny+_t8+Xx1*q^=(no^V>!qU{PK(&m zXRYt%J%*XMB{xaH*van|2PT|MvJr?6&Qhg?JvuB`CX0Q)YuwaGtB7dt(M~K5aCvMO zJ!Bn4HB>ne$U%fjMV<}Ags#HbcIPoNULzlKP^8H_Es2gJv;9*KMFo2`0_}99DUmog zyyMZVM?FPBBfV+2gusST#vVt-QsZ@zO1>Hg>GH?(Z@%wHx}7GEc(wtqBZrUY9Hw_vdg%$6OuN(g`r7GEr(U=t@j# z_-8dzxToH-P8^ZiQClbeptAq&+M;1=4rlf8u!pF97ff&B0+o#%>H4< z6>l5}kbTbC;tKbp$vTP;o_1VT5B|&|y)%eri;djw=s2}+pp9x!5bTT33azoc9Bq>zXF+`HSaOCp>6 z&Kl&scvbQnr$gzo*$sFjPmOTBJqkT@b1p|lUHxnN5x5B(I004vtH##zn9;l+GrAqN zf>W$R^Go%#&T%hHiyZ&v(j1gc8X&Kw<#y(y7yOs?G3KxRss;5*KWLD>IPK)n`Ye3*Yiid(+L zT^wz&fni_$U2bL66hADa<3|QeL%Mmssp(&RQUBVT&$~q(S1{8^2C?Ct4RkN`f(`_2FV(;pl#`mfufZ9!8C8Sf7}A{<=#MsoV=Le zsb@?Q^!bP0l+XkK;J;nR literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_trips_search_guest.png b/app/src/main/res/drawable-xhdpi/ic_trips_search_guest.png new file mode 100644 index 0000000000000000000000000000000000000000..d0f3508f76a7c4cd0c2c9a495d5937f1fdebf4f7 GIT binary patch literal 1158 zcmV;11bO?3P)VPL^;*|0R zz&h;I!1ubmaR}}!0~Y{hE7$=u#kV8!{gdIm4KQEE7JyG;tYBdy4{n8V--aIM{2(?O zwgAv*R4icr5G^n zFyFCosMUcHIQD-LkIE7h-yCJq>j0lD?kF*_;At*Hc7)X4ymdVRR~KN>&U>^NQh~ zzHVtvOWUEMfa?0lcl7!@V)l;?84JYL?o^G@BZhnGwKX}u4{88< zgffYV_!Sg7C_eqX8IL_TIJz0Q&r0N*VyKif+r+13-(1gQNqHOBw)S(gC1WhF z1%QwL#@O8hHW>ig4m(U50HdVW0`xJWk~9F&e^n$&e>^QG4uDdEogYVeG4Gep66k#C YFB}oE8iglT3;+NC07*qoM6N<$ftK9z-{FtE zSG55TQ$WKL4T*nt7y4E^77OfpT*G!K@Nb2TX+q!Z-ot{Q7nyZaP}Hf8oyQs~i|Q{2v!g;pDTGvyc&Y&~-lvR8p%Drno>n`b1*^ zi>XYheD}faodqIACu*0aZIJ>>rz(gkUew{2Q51LRTO5~cm|-v3wJr|ZWJvt=9OvHeY4{+RBWBXTn<+hJ|9Q`~Ti~QveJD22WQ%mvv4FO#qGu BbbtT= literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/search.png b/app/src/main/res/drawable-xhdpi/search.png new file mode 100644 index 0000000000000000000000000000000000000000..10550f92fdb86b665b4fdf0bed4d9230f187581a GIT binary patch literal 2379 zcmeHIX*Zh*7=4K#nG|gu%M?RYN{ZS_Vr%VUn^=Co#TV0QWtu>`}!jjTWy%eg?W0ZFol=y*@W2-a+^@gEbCh?62x%?vBtG@^U zpd6gFg$Hfoy*KPvq_@twv!9x;@Bv}&vp@6mrjR{|_5>14+L z{$Zjt;~4z`aI0+Ii%}op5fOfG4|tbz+K_*n(O6xe2=-PE&U6WOWQcRzKC0%Gh`^2I zw8ESbaZ=T1Q||Givh3E>`M>&`CQm(kAp?q^J=px`GsUxWu=2(7cp9^}>qhV6e@^0PoYHMd-_ses)#%l5$ylGSx}7zkZHJ9-WM?kOAVx; zYS`3sv*1srq*XV;A)PC#U^{+%(vlKuD20Yn_>=mIcgii7NT-apFkAuyDsF>a4utE7i>Pc=CmaQ*(rUHK8o! z#0aa%%qd7m$z_LQ$_a!U`LbXvsG$sP(bY-#l;SE$#Q7{pJ8MIx+3Or39wXd-IH(f( znBin|AR~nswt>m|uX`I=vLrmyza5=K*orU0dGg=|-V0Q}LcYRC6RTvOQsl#61m2@Ed{?mx0;9JF(p0S&$=M{2D zM!0r9Y4^e#cR`diMy*E^)T?kN-08SjRci|yL=OeVvQ4txuL^xOAhrz%Z>g3yA-8{G!IEct`tq@&Vs7R=A!gpXUxvDF0U5MlP?2C=HSpk4s9otV|*ox!M zc4m}xOYQWDK563xIciw>ylV&#%jCGp!Z!8Vqx{T&@d%V3vsTJbX>wbmgf^Wy2WCnZ zKikFLBOU~?Hq4OFn-ZhCjc2w$3M{|Z$TQ~Wo6x|+hZ-pKn0|6ZOw1W4qwPmx-;5HX zKKe|CPpf4FSkG?hoE)6n_npbX0Z@FtBUOekQJ-p7{`zS^z0#SFrd)+pwP$-?NwQep z(<=ZT!{%CH9yW*tp6-ZX+0A3e@zrAMw)JK<_JY4JC^Ax52*G`WU21d_TvCtqsW#@C zp+cUEf>dsG|NeC$dKP`8sg?h30z2Rx6MO%l;9=AlOEizz(iA~ve19uA5xJT7) + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_airbnb_condition_gray.xml b/app/src/main/res/drawable/bg_airbnb_condition_gray.xml new file mode 100644 index 0000000..164e26a --- /dev/null +++ b/app/src/main/res/drawable/bg_airbnb_condition_gray.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_tab.xml b/app/src/main/res/drawable/bg_tab.xml new file mode 100644 index 0000000..ff90e15 --- /dev/null +++ b/app/src/main/res/drawable/bg_tab.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_tab_white.xml b/app/src/main/res/drawable/bg_tab_white.xml new file mode 100644 index 0000000..30db789 --- /dev/null +++ b/app/src/main/res/drawable/bg_tab_white.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/divider_padding.xml b/app/src/main/res/drawable/divider_padding.xml new file mode 100644 index 0000000..1a8b1a0 --- /dev/null +++ b/app/src/main/res/drawable/divider_padding.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_airbnb.xml b/app/src/main/res/layout/activity_airbnb.xml new file mode 100644 index 0000000..3c8cfae --- /dev/null +++ b/app/src/main/res/layout/activity_airbnb.xml @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_iread.xml b/app/src/main/res/layout/activity_iread.xml new file mode 100644 index 0000000..c40556f --- /dev/null +++ b/app/src/main/res/layout/activity_iread.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_item.xml b/app/src/main/res/layout/fragment_item.xml index bd20500..087557b 100644 --- a/app/src/main/res/layout/fragment_item.xml +++ b/app/src/main/res/layout/fragment_item.xml @@ -1,5 +1,6 @@ #E7EEFE #1E1E1E + + + #128488 + #359A9D + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 82188f5..ea886c9 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -14,4 +14,22 @@ 8dp 4dp + + + + 16dp + 12dp + 10dp + + 24dp + 20dp + 60dp + 56dp + 68dp + 260dp + + 180dp + 310dp + + 16sp diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 08516af..84da759 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -19,12 +19,24 @@ @color/text + + - +