Repository: iielse/learn-coordinatorlayout-behavior
Branch: master
Commit: 306d8c9cc401
Files: 65
Total size: 128.6 KB
Directory structure:
gitextract_cqq1i4ei/
├── .gitignore
├── .idea/
│ ├── gradle.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── runConfigurations.xml
│ └── vcs.xml
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── libs/
│ │ └── overscroll-release-v1.1-20160904.jar
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── learn/
│ │ ├── App.kt
│ │ ├── BaseActivity.kt
│ │ ├── Bus.kt
│ │ ├── BusEvent.kt
│ │ ├── Candy.kt
│ │ ├── Data.kt
│ │ ├── business/
│ │ │ ├── MerchantActivity.kt
│ │ │ ├── MerchantCommentLayout.kt
│ │ │ ├── MerchantContentLayout.kt
│ │ │ ├── MerchantFoodLayout.kt
│ │ │ ├── MerchantInfoLayout.kt
│ │ │ ├── MerchantPageBehavior.kt
│ │ │ ├── MerchantPageLayout.kt
│ │ │ ├── MerchantSettleLayout.kt
│ │ │ ├── MerchantTitleLayout.kt
│ │ │ ├── MyEventLayout.kt
│ │ │ └── TicketView.kt
│ │ └── view/
│ │ ├── ScrollHelper.kt
│ │ ├── SmartTabLayout1.java
│ │ ├── ViewPager2.java
│ │ └── ViewState.kt
│ └── res/
│ ├── drawable/
│ │ ├── ic_launcher_background.xml
│ │ ├── merchant_search_shape.xml
│ │ ├── settle_submit_shape.xml
│ │ ├── shadow_b_000_shape.xml
│ │ ├── shadow_b_fff_shape.xml
│ │ ├── tab_title_selector.xml
│ │ └── transparent.xml
│ ├── layout/
│ │ ├── merchant_activity.xml
│ │ ├── merchant_content_layout.xml
│ │ ├── merchant_food_list_content.xml
│ │ ├── merchant_food_list_content_image.xml
│ │ ├── merchant_food_list_recommend.xml
│ │ ├── merchant_food_list_recommend_cell.xml
│ │ ├── merchant_food_list_side.xml
│ │ ├── merchant_food_list_sticky_title.xml
│ │ ├── merchant_food_list_top.xml
│ │ ├── merchant_page_cell_layout.xml
│ │ ├── merchant_page_food_layout.xml
│ │ ├── merchant_page_layout.xml
│ │ ├── merchant_settle_layout.xml
│ │ ├── merchant_title_layout.xml
│ │ └── ticket_view.xml
│ └── values/
│ ├── frames.xml
│ └── strings.xml
├── app-behavior.apk
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
================================================
FILE: .idea/gradle.xml
================================================
================================================
FILE: .idea/misc.xml
================================================
================================================
FILE: .idea/modules.xml
================================================
================================================
FILE: .idea/runConfigurations.xml
================================================
================================================
FILE: .idea/vcs.xml
================================================
================================================
FILE: README.md
================================================
# behavior-learn
该项目是为了练习-> 使用`CoordinatorLayout.Behavior` 实现页面复杂联动效果
代码模仿实现美团商家详情界面内容联动

[download apk](https://github.com/iielse/behavior-learn/blob/master/app-behavior.apk)
开发使用知识点顺带涉及到:
1. Scroller+Handler 实现View自动滑动
2. View属性动画
3. 触摸事件分发机制
4. ConstraintLayout约束布局
emmmmmmm 继续加油咯~
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion COMPILE_SDK_VERSION as int
buildToolsVersion ANDROID_SUPPORT_VERSION
defaultConfig {
applicationId APPLICATION_ID
minSdkVersion MIN_SDK_VERSION as int
targetSdkVersion TARGET_SDK_VERSION as int
versionCode VERSION_CODE as int
versionName VERSION_NAME
flavorDimensions VERSION_CODE
multiDexEnabled true
ndk {
abiFilters 'armeabi'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.jniLibs.srcDirs = ['libs']
}
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/notice.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/dependencies.txt'
exclude 'META-INF/LGPL2.1'
}
}
dependencies {
implementation rootProject.ext.support_multidex
implementation rootProject.ext.support_support_v4
implementation rootProject.ext.support_appcompat_v7
implementation rootProject.ext.support_recyclerview_v7
implementation rootProject.ext.support_design
implementation 'com.android.support.constraint:constraint-layout:1.1.1'
implementation rootProject.ext.kotlin
implementation rootProject.ext.kotlin_stdlib
implementation rootProject.ext.kotlin_anko_common
implementation rootProject.ext.glide
annotationProcessor rootProject.ext.glide_compiler
implementation rootProject.ext.glide_transformations
implementation rootProject.ext.list_pull_to_refresh
implementation rootProject.ext.list_adapter
implementation rootProject.ext.eventbus
implementation files('libs/overscroll-release-v1.1-20160904.jar')
implementation 'com.oushangfeng:PinnedSectionItemDecoration:1.2.4'
implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar'
implementation 'com.hyman:flowlayout-lib:1.1.1'
}
repositories {
mavenCentral()
flatDir { dirs 'libs' }
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
================================================
FILE: app/src/main/java/com/example/learn/App.kt
================================================
package com.example.learn
import android.app.Application
import android.content.Context
import android.support.multidex.MultiDex
class App : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
override fun onCreate() {
super.onCreate()
INSTANCE = this
}
companion object {
private var INSTANCE: App? = null
@Synchronized
fun get(): App = INSTANCE!!
}
}
================================================
FILE: app/src/main/java/com/example/learn/BaseActivity.kt
================================================
package com.example.learn
import android.annotation.SuppressLint
import android.support.v7.app.AppCompatActivity
@SuppressLint("Registered")
open class BaseActivity : AppCompatActivity()
================================================
FILE: app/src/main/java/com/example/learn/Bus.kt
================================================
package com.example.learn
object Bus {
private var EVENT_ID_PRODUCER = 1
val FOOD_TOP_HEIGHT = EVENT_ID_PRODUCER++
val FOOD_RECOMMEND_HEIGHT = EVENT_ID_PRODUCER++
}
================================================
FILE: app/src/main/java/com/example/learn/BusEvent.kt
================================================
package com.example.learn
class BusEvent {
constructor(a: Int) {
act = a
}
constructor(a: Int, o: Any) : this(a) {
obj = o
}
constructor(a: Int, o: Any, o2: Any) : this(a, o) {
obj2 = o2
}
constructor(a: Int, o: Any, o2: Any, o3: Any) : this(a, o, o2) {
obj3 = o3
}
var act: Int = 0
var obj: Any? = null
var obj2: Any? = null
var obj3: Any? = null
}
================================================
FILE: app/src/main/java/com/example/learn/Candy.kt
================================================
package com.example.learn
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.support.v4.app.FragmentActivity
import android.support.v4.content.ContextCompat
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.view.animation.AnimationUtils
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.MultiTransformation
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
import jp.wasabeef.glide.transformations.BitmapTransformation
import org.greenrobot.eventbus.EventBus
val dispatcher = Handler(Looper.getMainLooper())
val crossFade = DrawableTransitionOptions().crossFade(200)
val centerCrop = RequestOptions().centerCrop().placeholder(android.R.color.transparent).priority(Priority.NORMAL)
val argbEvaluator = android.animation.ArgbEvaluator()
fun ImageView?.load(res: Any?, transform: List? = null) {
if (this == null) return
context.activity()?.let {
val requestOptions = if (transform != null) RequestOptions.bitmapTransform(MultiTransformation(transform)) else centerCrop
Glide.with(it).load(when (res) {
is Int?, is String?, is Uri?, is Drawable? -> res
else -> throw IllegalArgumentException("imageView load un support res type")
}).apply(requestOptions).transition(crossFade).into(this)
}
}
fun TextView?.text(res: Any?) {
if (this == null) return
text = when (res) {
is Int -> resString(res)
is String -> res
else -> throw IllegalArgumentException("imageView load un support res type")
}
}
fun Context?.activity(): Activity? {
if (this == null) return null
if (this.javaClass.name.contains("com.android.internal.policy.DecorContext")) {
try {
val field = this.javaClass.getDeclaredField("mPhoneWindow")
field.isAccessible = true
val obj = field.get(this)
val m1 = obj.javaClass.getMethod("getContext")
return (m1.invoke(obj)) as Activity
} catch (e: Exception) {
e.printStackTrace()
}
}
var context = this
while (context is ContextWrapper) {
if (context is Activity) {
return context
}
context = context.baseContext
}
return null
}
fun View?.activity(): Activity? {
if (this == null) return null
return context.activity()
}
fun Activity?.v4(): FragmentActivity? {
if (this == null) return null
return this as? FragmentActivity
}
fun Any.resDrawable(drawableRes: Int, scale: Float = 1F): Drawable =
ContextCompat.getDrawable(App.get(), drawableRes)!!.apply {
setBounds(0, 0, (minimumWidth * scale).toInt(), (minimumHeight * scale).toInt())
}
fun Any.resString(stringRes: Int): String = App.get().getString(stringRes)
fun Any.resDimension(dimensionRes: Int): Int = App.get().resources.getDimensionPixelSize(dimensionRes)
fun Any.dp(dp: Int): Int {
val dm = DisplayMetrics()
(App.get().getSystemService(Context.WINDOW_SERVICE) as WindowManager)
.defaultDisplay.getMetrics(dm)
return (dp * dm.density + 0.5f).toInt()
}
fun Any.screenWidth(): Int {
val dm = DisplayMetrics()
(App.get().getSystemService(Context.WINDOW_SERVICE) as WindowManager)
.defaultDisplay.getMetrics(dm)
return dm.widthPixels
}
fun Any.screenHeight(): Int {
val dm = DisplayMetrics()
(App.get().getSystemService(Context.WINDOW_SERVICE) as WindowManager)
.defaultDisplay.getMetrics(dm)
return dm.heightPixels
}
@SuppressLint("PrivateApi")
fun Any.statusBarHeight(): Int {
var statusHeight = -1
try {
val clazz = Class.forName("com.android.internal.R\$dimen")
val `object` = clazz.newInstance()
val height = Integer.parseInt(clazz.getField("status_bar_height").get(`object`).toString())
statusHeight = App.get().resources.getDimensionPixelSize(height)
} catch (e: Exception) {
e.printStackTrace()
}
return statusHeight
}
fun Any.toast(content: String) {
Toast.makeText(App.get(), content, Toast.LENGTH_SHORT).show()
}
fun Activity.postDelayed1(r: Runnable, delayMillis: Long = 0) {
dispatcher.postDelayed({
if (isFinishing) return@postDelayed
r.run()
}, delayMillis)
}
fun View.postDelayed1(r: Runnable, delayMillis: Long = 0) {
activity()?.postDelayed1(r, delayMillis)
}
fun Any.log(content: String, lv: Int = Log.DEBUG) {
when (lv) {
Log.DEBUG -> Log.d("candy", content)
Log.ERROR -> Log.e("candy", content)
}
}
fun Any.postEvent(a: Int, o: Any? = null, o2: Any? = null, o3: Any? = null) {
when {
o != null && o2 != null && o3 != null -> EventBus.getDefault().post(BusEvent(a, o, o2, o3))
o != null && o2 != null -> EventBus.getDefault().post(BusEvent(a, o, o2))
o != null -> EventBus.getDefault().post(BusEvent(a, o))
else -> EventBus.getDefault().post(BusEvent(a))
}
}
fun View.anim(animRes: Int, visible: Int = View.VISIBLE) {
if (visibility != visible) {
visibility = visible
startAnimation(AnimationUtils.loadAnimation(App.get(), animRes))
}
}
================================================
FILE: app/src/main/java/com/example/learn/Data.kt
================================================
package com.example.learn
import com.chad.library.adapter.base.entity.MultiItemEntity
import com.example.learn.business.*
object Data {
fun foodDetails(): List {
return listOf(
FoodTop(),
FoodRecommend(foodRecommends()),
FoodCover(R.mipmap.pic1),
FoodCover(R.mipmap.pic2),
FoodCover(R.mipmap.pic3),
FoodTitle("热销"),
FoodContent("皮蛋瘦肉粥", R.mipmap.pic4, "皮蛋瘦肉粥是非常受欢迎的粥,其中骚处自行体会..", 16F),
FoodContent("香菇瘦肉粥", R.mipmap.pic5, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 16F),
FoodContent("红枣桂圆粥", R.mipmap.pic6, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 16F),
FoodTitle("养颜甜粥"),
FoodContent("小米南瓜粥", R.mipmap.pic7, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 14F),
FoodContent("清火绿豆粥", R.mipmap.pic8, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 14F),
FoodContent("红心地瓜粥", R.mipmap.pic9, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 14F),
FoodContent("紫薯黑米粥", R.mipmap.pic10, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 16F),
FoodContent("红枣桂圆粥", R.mipmap.pic6, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 16F),
FoodContent("柠檬八宝粥", R.mipmap.pic11, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 17F),
FoodTitle("营养水果粥"),
FoodContent("苹果雪梨粥", R.mipmap.pic12, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 16F),
FoodContent("香蕉苹果粥", R.mipmap.pic13, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 16F),
FoodContent("香蕉雪梨粥", R.mipmap.pic14, "对于吃货来说:治愈系没事,不过一碗热腾腾的粥", 16F)
)
}
fun foodMenus(): List {
return listOf(
FoodTitle("进店须知"),
FoodTitle("热销"),
FoodTitle("养颜甜粥"),
FoodTitle("营养水果粥")
)
}
private fun foodRecommends(): List {
return listOf(
FoodContent("烧肉拼叉烧饭+肉包+可乐+虎邦辣椒酱", R.mipmap.pic15, "", 50.6F),
FoodContent("绿豆汤+小肉+卤蛋+脆笋片", R.mipmap.pic16, "", 50.6F),
FoodContent("冰镇绿豆汤", R.mipmap.pic15, "", 15F),
FoodContent("台式炒饭+可乐+葱油饼套餐", R.mipmap.pic16, "", 33F)
)
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantActivity.kt
================================================
package com.example.learn.business
import android.os.Bundle
import com.example.learn.BaseActivity
import com.example.learn.R
import com.example.learn.log
import kotlinx.android.synthetic.main.merchant_activity.*
class MerchantActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.merchant_activity)
initialView()
log("MerchantActivity onCreate")
}
private fun initialView() {
layContent.laySettle = laySettle
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantCommentLayout.kt
================================================
package com.example.learn.business
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import com.example.learn.R
import kotlinx.android.synthetic.main.merchant_page_cell_layout.view.*
class MerchantCommentLayout(context: Context) : FrameLayout(context), ScrollableViewProvider {
override fun getScrollableView(): View {
return vRecycler
}
init {
LayoutInflater.from(context).inflate(R.layout.merchant_page_cell_layout, this)
initialData()
}
private fun initialData() {
vRecycler.setBackgroundColor(0xFFEFEFEF.toInt())
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantContentLayout.kt
================================================
package com.example.learn.business
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.content.Context
import android.support.constraint.ConstraintLayout
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import com.example.learn.R
import com.example.learn.dp
import com.example.learn.load
import com.example.learn.view.stateRefresh
import com.example.learn.view.stateSave
import com.example.learn.view.statesChangeByAnimation
import jp.wasabeef.glide.transformations.BlurTransformation
import kotlinx.android.synthetic.main.merchant_content_layout.view.*
class MerchantContentLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) {
var laySettle: MerchantSettleLayout? = null
private var firstLayout: Boolean = false
private var isExpanded = false
private var effected: Float = 0f
init {
LayoutInflater.from(context).inflate(R.layout.merchant_content_layout, this)
vCover.load(R.mipmap.cover, listOf(BlurTransformation()))
layScroll.setOnTouchListener { _, _ -> !isExpanded }
vTicket1.set(3, 27, "2018.06.12")
vTicket2.set(5, 40, "2018.06.12")
vSwitch.setOnClickListener { switch(!isExpanded) }
vHide.setOnClickListener { switch(!isExpanded) }
}
private fun animViews(): Array = arrayOf(laySimple, vAvatar, vMerchantName, layTicket, vTicket1, vTicket2, vSwitchIcon)
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (!firstLayout) {
firstLayout = true
laySimple.stateSave(R.id.vs1).a(1F)
laySimple.stateSave(R.id.vs2).a(0F)
vMerchantName.stateSave(R.id.vs1).a(0F)
vMerchantName.stateSave(R.id.vs2).a(1F)
layTicket.stateSave(R.id.vs1).mt(dp(15))
layTicket.stateSave(R.id.vs2).mt(dp(70))
vSwitchIcon.stateSave(R.id.vs1)
vSwitchIcon.stateSave(R.id.vs2).r(180F)
vAvatar.stateSave(R.id.vs1)
val tx: Float = ((width - vAvatar.width) / 2 - (vAvatar.layoutParams as MarginLayoutParams).leftMargin).toFloat()
vAvatar.stateSave(R.id.vs2).tx(tx).ty(dp(10).toFloat())
}
}
// 效果简单实现,具体内容应该根据业务动态计算变化高度区间。
fun effectByOffset(transY: Float) {
val p2: Float = when {
transY <= dp(10) -> 0F
transY > dp(10) && transY < dp(30) -> (transY - dp(10)) / dp(20)
else -> 1F
}
vt2.alpha = p2
vt222.alpha = p2
val p3: Float = when {
transY <= dp(40) -> 0F
transY > dp(40) && transY < dp(60) -> (transY - dp(40)) / dp(20)
else -> 1F
}
vt3.alpha = p3
vt333.alpha = p3
val p4: Float = when {
transY <= dp(70) -> 0F
transY > dp(70) && transY < dp(90) -> (transY - dp(70)) / dp(20)
else -> 1F
}
vt4.alpha = p4
vt444.alpha = p4
val p5: Float = when {
transY <= dp(110) -> 0F
transY > dp(110) && transY < dp(130) -> (transY - dp(110)) / dp(20)
else -> 1F
}
vt5.alpha = p5
vt555.alpha = p5
effected = when {
transY <= dp(140) -> 0F
transY > dp(140) && transY < dp(230) -> (transY - dp(140)) / dp(90)
else -> 1F
}
animViews().forEach { it.stateRefresh(R.id.vs1, R.id.vs2, effected) }
}
fun switch(expanded: Boolean, byScrollerSlide: Boolean = false) {
if (isExpanded == expanded) {
return
}
layScroll.scrollTo(0, 0)
isExpanded = expanded // 目标
val start = effected
val end = if (expanded) 1F else 0F
statesChangeByAnimation(animViews(), R.id.vs1, R.id.vs2, start, end,
null, if (!byScrollerSlide) internalAnimListener else null, 300)
laySettle?.switch(isExpanded)
}
var animListener: AnimatorListenerAdapter1? = null
private val internalAnimListener: AnimatorListenerAdapter = object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
animListener?.onAnimationStart(animation, isExpanded)
}
}
interface AnimatorListenerAdapter1 {
fun onAnimationStart(animation: Animator?, toExpanded: Boolean)
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantFoodLayout.kt
================================================
package com.example.learn.business
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import com.chad.library.adapter.base.BaseMultiItemQuickAdapter
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.chad.library.adapter.base.entity.MultiItemEntity
import com.example.learn.*
import com.oushangfeng.pinnedsectionitemdecoration.PinnedHeaderItemDecoration
import com.oushangfeng.pinnedsectionitemdecoration.utils.FullSpanUtil
import kotlinx.android.synthetic.main.merchant_page_food_layout.view.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class MerchantFoodLayout(context: Context) : FrameLayout(context), ScrollableViewProvider {
var topHeight: Int = 0
var recommendHeight: Int = 0
init {
LayoutInflater.from(context).inflate(R.layout.merchant_page_food_layout, this)
initialData()
}
private fun initialData() {
val foodAdapter = FoodAdapter(Data.foodDetails())
vRecycler.addItemDecoration(PinnedHeaderItemDecoration.Builder(FoodAdapter.TYPE_TITLE)
.setDividerId(R.drawable.transparent)
.create())
vRecycler.adapter = foodAdapter
foodAdapter.openLoadAnimation()
vRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
var totalDy = 0
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
totalDy -= dy
val transY = if (totalDy > -(topHeight + recommendHeight)) totalDy else -(topHeight + recommendHeight)
vSide.translationY = transY.toFloat()
}
})
vSide.isNestedScrollingEnabled = false
vSide.adapter = SideAdapter(Data.foodMenus())
}
override fun getScrollableView(): View {
return vRecycler
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
EventBus.getDefault().register(this)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
EventBus.getDefault().unregister(this)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun handleBusEvent(event: BusEvent) {
when (event.act) {
Bus.FOOD_TOP_HEIGHT -> {
topHeight = event.obj as Int
adjustSideLayoutPosition()
}
Bus.FOOD_RECOMMEND_HEIGHT -> {
recommendHeight = event.obj as Int
adjustSideLayoutPosition()
}
}
}
private fun adjustSideLayoutPosition() {
val lp = (vSide.layoutParams as MarginLayoutParams)
if (lp.topMargin != topHeight + recommendHeight) {
lp.topMargin = topHeight + recommendHeight
lp.height = screenHeight() - resDimension(R.dimen.title_height) - resDimension(R.dimen.merchant_tab_height)
vSide.layoutParams = lp
vSide.anim(android.R.anim.fade_in, View.VISIBLE)
}
}
}
class FoodTop : MultiItemEntity {
override fun getItemType(): Int = FoodAdapter.TYPE_TOP
}
class FoodRecommend(val data: List) : MultiItemEntity {
override fun getItemType(): Int = FoodAdapter.TYPE_RECOMMEND
}
class FoodCover(val url: Int) : MultiItemEntity {
override fun getItemType(): Int = FoodAdapter.TYPE_CONTENT_IMAGE
}
class FoodTitle(val title: String) : MultiItemEntity {
override fun getItemType(): Int = FoodAdapter.TYPE_TITLE
}
class FoodContent(val name: String, val icon: Int, val desc: String, val price: Float) : MultiItemEntity {
override fun getItemType(): Int = FoodAdapter.TYPE_CONTENT
}
class FoodAdapter(data: List) : BaseMultiItemQuickAdapter(data) {
companion object {
private var TYPE_PRODUCER = 1
val TYPE_TOP = TYPE_PRODUCER++
val TYPE_RECOMMEND = TYPE_PRODUCER++
val TYPE_CONTENT_IMAGE = TYPE_PRODUCER++
val TYPE_TITLE = TYPE_PRODUCER++
val TYPE_CONTENT = TYPE_PRODUCER++
}
init {
addItemType(TYPE_TOP, R.layout.merchant_food_list_top)
addItemType(TYPE_RECOMMEND, R.layout.merchant_food_list_recommend)
addItemType(TYPE_CONTENT_IMAGE, R.layout.merchant_food_list_content_image)
addItemType(TYPE_TITLE, R.layout.merchant_food_list_sticky_title)
addItemType(TYPE_CONTENT, R.layout.merchant_food_list_content)
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
FullSpanUtil.onAttachedToRecyclerView(recyclerView, this, TYPE_TITLE)
}
override fun onViewAttachedToWindow(holder: BaseViewHolder) {
super.onViewAttachedToWindow(holder)
FullSpanUtil.onViewAttachedToWindow(holder, this, TYPE_TITLE)
}
override fun convert(helper: BaseViewHolder, item: MultiItemEntity) {
when (helper.itemViewType) {
TYPE_TOP -> {
helper.itemView.postDelayed1(Runnable { postEvent(Bus.FOOD_TOP_HEIGHT, helper.itemView.height) })
}
TYPE_RECOMMEND -> {
helper.itemView.postDelayed1(Runnable { postEvent(Bus.FOOD_RECOMMEND_HEIGHT, helper.itemView.height) })
val view: RecyclerView = helper.getView(R.id.vRecommends)
view.adapter = FoodRecommendCellAdapter((item as FoodRecommend).data)
}
TYPE_CONTENT_IMAGE -> {
(item as FoodCover).apply { helper.setImageUrl(R.id.vImage, url) }
}
TYPE_TITLE -> {
(item as FoodTitle).apply { helper.setText(R.id.vTitle, title) }
}
TYPE_CONTENT -> {
(item as FoodContent).apply {
helper.setText(R.id.vPrice, "¥$price")
.setText(R.id.vName, name)
.setText(R.id.vDesc, desc)
.setImageUrl(R.id.vIcon, icon)
}
}
}
}
}
fun BaseViewHolder.setImageUrl(viewId: Int, imageUrl: Int): BaseViewHolder {
val view: ImageView = getView(viewId)
view.load(imageUrl)
return this
}
class FoodRecommendCellAdapter(data: List) : BaseQuickAdapter(data) {
init {
mLayoutResId = R.layout.merchant_food_list_recommend_cell
}
override fun convert(helper: BaseViewHolder, item: FoodContent) {
(helper.itemView.layoutParams as ViewGroup.MarginLayoutParams).leftMargin = if (mData.indexOf(item) != 0) dp(2) else 0
helper.setText(R.id.vPrice, "¥${item.price}")
.setText(R.id.vName, item.name)
.setImageUrl(R.id.vImage, item.icon)
}
}
class SideAdapter(data: List) : BaseQuickAdapter(data) {
init {
mLayoutResId = R.layout.merchant_food_list_side
}
override fun convert(helper: BaseViewHolder, item: FoodTitle) {
item.apply { helper.setText(R.id.vTitle, title) }
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantInfoLayout.kt
================================================
package com.example.learn.business
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import com.example.learn.R
import com.example.learn.log
import kotlinx.android.synthetic.main.merchant_page_cell_layout.view.*
class MerchantInfoLayout(context: Context) : FrameLayout(context), ScrollableViewProvider {
override fun getScrollableView(): View {
return vRecycler
}
init {
LayoutInflater.from(context).inflate(R.layout.merchant_page_cell_layout, this)
initialData()
}
private fun initialData() {
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantPageBehavior.kt
================================================
package com.example.learn.business
import android.animation.Animator
import android.content.Context
import android.graphics.Color
import android.support.design.widget.CoordinatorLayout
import android.util.AttributeSet
import android.view.View
import android.widget.Scroller
import com.example.learn.R
import com.example.learn.argbEvaluator
import com.example.learn.dp
import com.example.learn.view.ViewPager2
import kotlinx.android.synthetic.main.merchant_page_layout.view.*
class MerchantPageBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior(context, attrs) {
private lateinit var selfView: MerchantPageLayout
private lateinit var layTitle: MerchantTitleLayout // 商店标题
private lateinit var vPager: ViewPager2 // 商品菜单所在pager
private lateinit var layContent: MerchantContentLayout // 商店详情
private lateinit var laySettle: MerchantSettleLayout
private val pagingTouchSlop = dp(5)
private var horizontalPagingTouch = 0 // 菜单横项列表(推荐商品)内容的触摸滑动距离
private var isScrollRecommends = false
private var verticalPagingTouch = 0 // 菜单竖项列表(商品,评价,商家)内容的触摸滑动距离
private var simpleTopDistance = 0
private var isScrollToFullFood = false // 上滑显示商品菜单
private var isScrollToHideFood = false // 下滑显示商店详情
private val scroller = Scroller(context)
private val scrollDuration = 800
private val handler = android.os.Handler()
private val flingRunnable = object : Runnable {
override fun run() {
if (scroller.computeScrollOffset()) {
selfView.translationY = scroller.currY.toFloat()
layContent.effectByOffset(selfView.translationY)
laySettle.effectByOffset(selfView.translationY)
handler.post(this)
} else {
isScrollToHideFood = false
}
}
}
private val mAnimListener = object : MerchantContentLayout.AnimatorListenerAdapter1 {
override fun onAnimationStart(animation: Animator?, toExpanded: Boolean) {
if (toExpanded) {
val defaultDisplayHeight = (selfView.height - simpleTopDistance)
scroller.startScroll(0, selfView.translationY.toInt(), 0, (defaultDisplayHeight - selfView.translationY).toInt(), scrollDuration)
} else {
scroller.startScroll(0, selfView.translationY.toInt(), 0, (-selfView.translationY).toInt(), scrollDuration)
}
handler.post(flingRunnable)
isScrollToHideFood = true
}
}
override fun onLayoutChild(parent: CoordinatorLayout, child: MerchantPageLayout, layoutDirection: Int): Boolean {
selfView = child
vPager = child.findViewById(R.id.vPager)
val lp = selfView.layoutParams as CoordinatorLayout.LayoutParams
if (lp.height == CoordinatorLayout.LayoutParams.MATCH_PARENT) {
simpleTopDistance = lp.topMargin - layTitle.height
lp.height = parent.height - layTitle.height
child.layoutParams = lp
return true
}
return super.onLayoutChild(parent, child, layoutDirection)
}
override fun layoutDependsOn(parent: CoordinatorLayout, child: MerchantPageLayout, dependency: View): Boolean {
when {
dependency.id == R.id.layTitle -> layTitle = dependency as MerchantTitleLayout
dependency.id == R.id.layContent -> layContent = (dependency as MerchantContentLayout).apply { animListener = mAnimListener }
dependency.id == R.id.laySettle -> laySettle = dependency as MerchantSettleLayout
else -> return false
}
return true
}
override fun onDependentViewChanged(parent: CoordinatorLayout, child: MerchantPageLayout, dependency: View): Boolean = true
override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: MerchantPageLayout, directTargetChild: View, target: View, axes: Int, type: Int): Boolean = true
override fun onNestedScrollAccepted(coordinatorLayout: CoordinatorLayout, child: MerchantPageLayout, directTargetChild: View, target: View, axes: Int, type: Int) {
scroller.abortAnimation()
isScrollToHideFood = false
super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, axes, type)
}
override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: MerchantPageLayout, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
if (isScrollToHideFood) {
consumed[1] = dy
return // scroller 滑动中.. do nothing
}
verticalPagingTouch += dy
if (vPager.isScrollable && Math.abs(verticalPagingTouch) > pagingTouchSlop) {
vPager.isScrollable = false // 屏蔽 pager横向滑动干扰
}
horizontalPagingTouch += dx
if (R.id.vRecommends == target.id) {
if (!isScrollRecommends) {
consumed[0] = dx
if (vPager.isScrollable && Math.abs(horizontalPagingTouch) > pagingTouchSlop) isScrollRecommends = true
}
if (isScrollRecommends) {
consumed[1] = dy
return // 横项滑动推荐列表中
}
}
if ((child.translationY < 0 || (child.translationY == 0F && dy > 0)) && !child.canScrollVertically()) {
val effect = layTitle.effectByOffset(dy)
selfView.vSmartTab.setBackgroundColor(argbEvaluator.evaluate(effect, Color.WHITE, 0xFFFAFAFA.toInt()) as Int)
val transY = -simpleTopDistance * effect
if (transY != child.translationY) {
child.translationY = transY
consumed[1] = dy
}
if (type == 1) {
isScrollToFullFood = true
}
} else if ((child.translationY > 0 || (child.translationY == 0F && dy < 0)) && !child.canScrollVertically()) {
if (isScrollToFullFood) {
child.translationY = 0F // top fling to bottom
} else {
child.translationY -= dy
layContent.effectByOffset(child.translationY)
laySettle.effectByOffset(child.translationY)
}
consumed[1] = dy
}
}
override fun onNestedPreFling(coordinatorLayout: CoordinatorLayout, child: MerchantPageLayout, target: View, velocityX: Float, velocityY: Float): Boolean {
return onUserStopDragging()
}
override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: MerchantPageLayout, target: View, type: Int) {
isScrollToFullFood = false
verticalPagingTouch = 0
vPager.isScrollable = true
horizontalPagingTouch = 0
isScrollRecommends = false
if (!isScrollToHideFood) {
onUserStopDragging()
}
}
private fun onUserStopDragging(): Boolean {
if (selfView.translationY < 0f) {
return false
}
val defaultDisplayHeight = (selfView.height - simpleTopDistance)
if (defaultDisplayHeight * 0.4F > selfView.translationY) {
scroller.startScroll(0, selfView.translationY.toInt(), 0, (-selfView.translationY).toInt(), scrollDuration)
layContent.switch(false, true)
laySettle.switch(false)
} else {
scroller.startScroll(0, selfView.translationY.toInt(), 0, (defaultDisplayHeight - selfView.translationY).toInt(), scrollDuration)
layContent.switch(true, true)
laySettle.switch(true)
}
handler.post(flingRunnable)
isScrollToHideFood = true
return true
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantPageLayout.kt
================================================
package com.example.learn.business
import android.content.Context
import android.support.v4.view.PagerAdapter
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.example.learn.R
import kotlinx.android.synthetic.main.merchant_page_layout.view.*
class MerchantPageLayout(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
lateinit var pagerAdapter: MerchantPageAdapter
init {
LayoutInflater.from(context).inflate(R.layout.merchant_page_layout, this)
}
override fun onFinishInflate() {
super.onFinishInflate()
pagerAdapter = MerchantPageAdapter(context)
vPager.adapter = pagerAdapter
vSmartTab.setViewPager(vPager)
}
fun canScrollVertically(): Boolean {
val view = (pagerAdapter.getItem(vPager.currentItem) as ScrollableViewProvider).getScrollableView()
return view.canScrollVertically(-1)
}
}
class MerchantPageAdapter(context: Context) : PagerAdapter() {
private val layFood = MerchantFoodLayout(context)
private val layInfo = MerchantInfoLayout(context)
private val layComment = MerchantCommentLayout(context)
override fun getCount(): Int = 3
override fun isViewFromObject(view: View, `object`: Any): Boolean = view == `object`
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) = container.removeView(`object` as View)
override fun getPageTitle(position: Int): CharSequence = when (position) {
0 -> "点菜"
1 -> "评论(9999+)"
2 -> "商家"
else -> ""
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val content = getItem(position)
container.addView(content)
return content
}
fun getItem(position: Int): View {
return when (position) {
0 -> layFood
1 -> layComment
2 -> layInfo
else -> throw RuntimeException("getItem error position $position")
}
}
}
interface ScrollableViewProvider {
fun getScrollableView(): View
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantSettleLayout.kt
================================================
package com.example.learn.business
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.content.Context
import android.support.constraint.ConstraintLayout
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import com.example.learn.R
import com.example.learn.dp
import com.example.learn.view.stateRefresh
import com.example.learn.view.stateSave
import com.example.learn.view.statesChangeByAnimation
class MerchantSettleLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) {
private var firstLayout: Boolean = false
private var isExpanded = false // layContent 内容是否展开查看中
private var effected: Float = 0f
init {
LayoutInflater.from(context).inflate(R.layout.merchant_settle_layout, this)
}
private fun animViews(): Array = arrayOf(this)
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (!firstLayout) {
firstLayout = true
stateSave(R.id.vs1).a(1F)
stateSave(R.id.vs2).a(0F)
}
}
// 效果简单实现,具体内容应该根据业务动态计算变化高度区间。
fun effectByOffset(transY: Float) {
effected = when {
transY <= dp(110) -> 0F
transY > dp(110) && transY < dp(140) -> (transY - dp(110)) / dp(30)
else -> 1F
}
animViews().forEach { it.stateRefresh(R.id.vs1, R.id.vs2, effected) }
}
fun switch(expanded: Boolean) {
if (isExpanded == expanded) {
return
}
isExpanded = expanded // 目标
val start = effected
val end = if (expanded) 1F else 0F
statesChangeByAnimation(animViews(), R.id.vs1, R.id.vs2, start, end,
null, object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
visibility = View.VISIBLE
}
override fun onAnimationEnd(animation: Animator?) {
if (isExpanded) visibility = View.INVISIBLE
}
}, 300)
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MerchantTitleLayout.kt
================================================
package com.example.learn.business
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.support.v4.graphics.drawable.DrawableCompat
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.FrameLayout
import com.example.learn.R
import com.example.learn.argbEvaluator
import com.example.learn.dp
import com.example.learn.resDimension
import com.example.learn.resDrawable
import kotlinx.android.synthetic.main.merchant_title_layout.view.*
class MerchantTitleLayout(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
private val adInterpolator = AccelerateDecelerateInterpolator()
private val offsetMax = resDimension(R.dimen.merchant_offset).toFloat()
private var offset = 0F
private val drawableBack = resDrawable(R.mipmap.back_white)
private val drawableSearch = resDrawable(R.mipmap.icon_search)
private val drawableCollection = resDrawable(R.mipmap.icon_collection)
private val drawableTogether = resDrawable(R.mipmap.icon_together)
private val drawableMenu = resDrawable(R.mipmap.icon_menu)
init {
LayoutInflater.from(context).inflate(R.layout.merchant_title_layout, this)
}
fun effectByOffset(dy: Int): Float {
if (dy > 0 && offset == offsetMax) return 1F
else if (dy < 0 && offset == 0F) return 0F
offset += dy
if (offset > offsetMax) offset = offsetMax
else if (offset < 0) offset = 0F
val effect = adInterpolator.getInterpolation(offset / offsetMax)
setBackgroundColor(argbEvaluator.evaluate(effect, Color.TRANSPARENT, 0xFFFAFAFA.toInt()) as Int)
val e: Int = argbEvaluator.evaluate(effect, Color.WHITE, 0xFF646464.toInt()) as Int
vBack.setImageDrawable(tintDrawable(drawableBack, ColorStateList.valueOf(e)))
vTogether.setImageDrawable(tintDrawable(drawableTogether, ColorStateList.valueOf(e)))
vMenu.setImageDrawable(tintDrawable(drawableMenu, ColorStateList.valueOf(e)))
vCollection.setImageDrawable(tintDrawable(drawableCollection, ColorStateList.valueOf(e)))
vSearch.setImageDrawable(tintDrawable(drawableSearch, ColorStateList.valueOf(e)))
vSearch.scaleX = (1 - 0.4 * effect).toFloat()
vSearch.scaleY = (1 - 0.4 * effect).toFloat()
vSearch.translationX = -(vSearchBorder.width - vSearch.width + dp(3)) * effect
vSearchBorder.alpha = effect
vSearchBorder.pivotX = vSearchBorder.width.toFloat()
vSearchBorder.scaleX = (0.2 + 0.8 * effect).toFloat()
vSearchHint.alpha = effect
vSearchHint.translationX = (vSearchHint.width / 3) * (1 - effect)
return effect
}
private fun tintDrawable(drawable: Drawable, colors: ColorStateList): Drawable {
val wrappedDrawable = DrawableCompat.wrap(drawable)
DrawableCompat.setTintList(wrappedDrawable, colors)
return wrappedDrawable
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/MyEventLayout.kt
================================================
package com.example.learn.business
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ViewConfiguration
import android.widget.FrameLayout
class MyEventLayout(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
private var needDispatchDown = false
private var mLastMoveEvent: MotionEvent? = null
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
return true
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
needDispatchDown = true
}
MotionEvent.ACTION_MOVE -> {
dispatchHorizontalTouchEventToChild(ev)
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
needDispatchDown = false
}
}
mLastMoveEvent = ev
return true
}
private fun dispatchHorizontalTouchEventToChild(current: MotionEvent) {
mLastMoveEvent?.apply {
if (needDispatchDown) {
val d = MotionEvent.obtain(downTime, eventTime + ViewConfiguration.getLongPressTimeout(), MotionEvent.ACTION_DOWN, current.x, y, metaState)
getChildAt(0).onTouchEvent(d)
needDispatchDown = false
}
val e = MotionEvent.obtain(downTime, eventTime + ViewConfiguration.getLongPressTimeout(), MotionEvent.ACTION_MOVE, current.x, y, metaState)
getChildAt(0).onTouchEvent(e)
}
}
}
================================================
FILE: app/src/main/java/com/example/learn/business/TicketView.kt
================================================
package com.example.learn.business
import android.content.Context
import android.support.constraint.ConstraintLayout
import android.util.AttributeSet
import android.view.LayoutInflater
import com.example.learn.R
import com.example.learn.view.AnimationUpdateListener
import com.example.learn.view.stateRefresh
import com.example.learn.view.stateSave
import com.example.learn.text
import kotlinx.android.synthetic.main.ticket_view.view.*
class TicketView(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs), AnimationUpdateListener {
private var firstLayout: Boolean = false
init {
LayoutInflater.from(context).inflate(R.layout.ticket_view, this)
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (!firstLayout) {
firstLayout = true
vBorder1.stateSave(R.id.vs1).a(1F)
vBorder1.stateSave(R.id.vs2).ws(3.8F).hs(3.8F).a(0F)
vBorder2.stateSave(R.id.vs1).a(0F)
vBorder2.stateSave(R.id.vs2).ws(3.8F).hs(3.8F).a(1F)
vSimple.stateSave(R.id.vs1)
vSimple.stateSave(R.id.vs2).a(0f)
layDetail.stateSave(R.id.vs1)
layDetail.stateSave(R.id.vs2).sx(1F).sy(1F).a(1F)
}
}
fun set(amount: Int, limit: Int, expireTime: String) {
vSimple.text("领¥$amount")
vDetail1.text("¥$amount")
vDetail2.text("满$limit 可用")
vDetail3.text("有效期至$expireTime")
}
override fun onAnimationUpdate(tag1: Int, tag2: Int, p: Float) {
arrayOf(vBorder1, vBorder2, vSimple, layDetail).forEach { it.stateRefresh(tag1, tag2, p) }
}
}
================================================
FILE: app/src/main/java/com/example/learn/view/ScrollHelper.kt
================================================
package com.example.learn.view
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import com.example.learn.log
object ScrollHelper {
open class OnScrollStateChangedListener {
open fun onScrollToBottom() {}
}
fun init(recyclerView: RecyclerView, callback: OnScrollStateChangedListener) {
if (recyclerView.layoutManager !is LinearLayoutManager) throw IllegalArgumentException("just support LinearLayoutManager")
val layoutManager: LinearLayoutManager = recyclerView.layoutManager as LinearLayoutManager
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
private var scrollDown = false
override fun onScrolled(vRecycler: RecyclerView?, dx: Int, dy: Int) {
scrollDown = if (layoutManager.reverseLayout) dy < 0 else dy > 0
}
override fun onScrollStateChanged(vRecycler: RecyclerView?, newState: Int) {
when (newState) {
RecyclerView.SCROLL_STATE_IDLE -> {
val lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition()
val totalItemCount = layoutManager.itemCount
log("onScrollStateChanged lastVisibleItem[$lastVisibleItem] totalItemCount[$totalItemCount] scrollDown[$scrollDown]")
if (lastVisibleItem >= totalItemCount - 1 && scrollDown) {
callback.onScrollToBottom()
log("onScrollStateChanged onScrollToBottom")
}
}
RecyclerView.SCROLL_STATE_DRAGGING -> {
}
}
}
})
}
open class OnScrollStateChangedListener2 {
open fun onScrollToTop() {}
}
fun init1(recyclerView: RecyclerView, callback: OnScrollStateChangedListener2) {
if (recyclerView.layoutManager !is LinearLayoutManager) throw IllegalArgumentException("just1 support LinearLayoutManager")
val layoutManager: LinearLayoutManager = recyclerView.layoutManager as LinearLayoutManager
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
private var scrollDown = false
override fun onScrolled(vRecycler: RecyclerView?, dx: Int, dy: Int) {
scrollDown = if (layoutManager.reverseLayout) dy < 0 else dy > 0
}
override fun onScrollStateChanged(vRecycler: RecyclerView?, newState: Int) {
when (newState) {
RecyclerView.SCROLL_STATE_IDLE -> {
val firstVisibleItem = layoutManager.findFirstCompletelyVisibleItemPosition()
log("onScrollStateChanged firstVisibleItem[$firstVisibleItem] scrollUp[${!scrollDown}]")
if (firstVisibleItem <= 0 && !scrollDown) {
callback.onScrollToTop()
log("onScrollStateChanged onScrollToTop")
}
}
RecyclerView.SCROLL_STATE_DRAGGING -> {
}
}
}
})
}
}
================================================
FILE: app/src/main/java/com/example/learn/view/SmartTabLayout1.java
================================================
package com.example.learn.view;
import android.content.Context;
import android.graphics.Typeface;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
public class SmartTabLayout1 extends com.ogaclejapan.smarttablayout.SmartTabLayout {
private ViewPager vPager;
private View vLastTab;
private ViewPager.OnPageChangeListener mSmartPageChangeListener;
public void setSmartPageChangeListener(ViewPager.OnPageChangeListener cb) {
mSmartPageChangeListener = cb;
}
public SmartTabLayout1(Context context) {
this(context, null);
}
public SmartTabLayout1(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void useFakeBoldSelectedTextTab() {
final ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mSmartPageChangeListener != null)
mSmartPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
if (mSmartPageChangeListener != null)
mSmartPageChangeListener.onPageSelected(position);
if (vLastTab != null) {
if (vLastTab instanceof TextView) {
((TextView) vLastTab).getPaint().setFakeBoldText(false);
}
}
vLastTab = getTabAt(position);
if (vLastTab instanceof TextView) {
((TextView) vLastTab).getPaint().setFakeBoldText(true);
}
}
@Override
public void onPageScrollStateChanged(int state) {
if (mSmartPageChangeListener != null)
mSmartPageChangeListener.onPageScrollStateChanged(state);
}
};
onPageChangeListener.onPageSelected(vPager.getCurrentItem());
setOnPageChangeListener(onPageChangeListener);
}
@Override
public void setViewPager(ViewPager viewPager) {
vPager = viewPager;
super.setViewPager(viewPager);
useFakeBoldSelectedTextTab();
}
@Override
protected TextView createDefaultTabView(CharSequence title) {
TextView textView = super.createDefaultTabView(title);
textView.setTypeface(Typeface.DEFAULT);
textView.setSingleLine(true);
textView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
return textView;
}
}
================================================
FILE: app/src/main/java/com/example/learn/view/ViewPager2.java
================================================
package com.example.learn.view;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class ViewPager2 extends ViewPager {
private boolean scrollable = true;
public ViewPager2(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public boolean isScrollable() {
return scrollable;
}
public void setScrollable(boolean scrollable) {
this.scrollable = scrollable;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return scrollable && super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return scrollable && super.onTouchEvent(ev);
}
}
================================================
FILE: app/src/main/java/com/example/learn/view/ViewState.kt
================================================
package com.example.learn.view
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
class ViewState {
var topMargin: Int = 0
var bottomMargin: Int = 0
var leftMargin: Int = 0
var rightMargin: Int = 0
var width: Int = 0
var height: Int = 0
var translationX: Float = 0F
var translationY: Float = 0F
var scaleX: Float = 0F
var scaleY: Float = 0F
var rotation: Float = 0F
var alpha: Float = 0F
fun sx(scaleX: Float): ViewState {
this.scaleX = scaleX
return this
}
fun sxBy(value: Float): ViewState {
this.scaleX *= value
return this
}
fun sy(scaleY: Float): ViewState {
this.scaleY = scaleY
return this
}
fun syBy(value: Float): ViewState {
this.scaleY *= value
return this
}
fun a(alpha: Float): ViewState {
this.alpha = alpha
return this
}
fun w(width: Int): ViewState {
this.width = width
return this
}
fun h(height: Int): ViewState {
this.height = height
return this
}
fun r(rotation: Float): ViewState {
this.rotation = rotation
return this
}
fun ws(s: Float): ViewState {
this.width = (width * s).toInt()
return this
}
fun hs(s: Float): ViewState {
this.height = (height * s).toInt()
return this
}
fun tx(translationX: Float): ViewState {
this.translationX = translationX
return this
}
fun ty(translationY: Float): ViewState {
this.translationY = translationY
return this
}
fun ml(leftMargin: Int): ViewState {
this.leftMargin = leftMargin
return this
}
fun mr(rightMargin: Int): ViewState {
this.rightMargin = rightMargin
return this
}
fun mt(topMargin: Int): ViewState {
this.topMargin = topMargin
return this
}
fun mn(bottomMargin: Int): ViewState {
this.bottomMargin = bottomMargin
return this
}
fun copy(view: View): ViewState {
this.width = view.width
this.height = view.height
this.translationX = view.translationX
this.translationY = view.translationY
this.scaleX = view.scaleX
this.scaleY = view.scaleY
this.rotation = view.rotation
this.alpha = view.alpha
(view.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
this.topMargin = it.topMargin
this.bottomMargin = it.bottomMargin
this.leftMargin = it.leftMargin
this.rightMargin = it.rightMargin
}
return this
}
}
fun View.stateSet(tag: Int, vs: ViewState) {
setTag(tag, vs)
}
fun View.stateRead(tag: Int): ViewState? {
return getTag(tag) as? ViewState
}
fun View.stateSave(tag: Int): ViewState {
val vs = stateRead(tag) ?: ViewState()
vs.copy(this)
stateSet(tag, vs)
return vs
}
fun View.stateRefresh(tag1: Int, tag2: Int, p: Float) {
if (this is AnimationUpdateListener) {
onAnimationUpdate(tag1, tag2, p)
} else {
val vs1 = stateRead(tag1)
val vs2 = stateRead(tag2)
if (vs1 != null && vs2 != null) {
if (vs1.translationX != vs2.translationX) translationX = vs1.translationX + (vs2.translationX - vs1.translationX) * p
if (vs1.translationY != vs2.translationY) translationY = vs1.translationY + (vs2.translationY - vs1.translationY) * p
if (vs1.scaleX != vs2.scaleX) scaleX = vs1.scaleX + (vs2.scaleX - vs1.scaleX) * p
if (vs1.scaleY != vs2.scaleY) scaleY = vs1.scaleY + (vs2.scaleY - vs1.scaleY) * p
if (vs1.rotation != vs2.rotation) rotation = (vs1.rotation + (vs2.rotation - vs1.rotation) * p) % 360
if (vs1.alpha != vs2.alpha) alpha = vs1.alpha + (vs2.alpha - vs1.alpha) * p
val o = layoutParams
var lpChanged = false
if (vs1.width != vs2.width) {
o.width = (vs1.width + (vs2.width - vs1.width) * p).toInt()
lpChanged = true
}
if (vs1.height != vs2.height) {
o.height = (vs1.height + (vs2.height - vs1.height) * p).toInt()
lpChanged = true
}
(o as? ViewGroup.MarginLayoutParams)?.let {
if (vs1.topMargin != vs2.topMargin) {
it.topMargin = (vs1.topMargin + (vs2.topMargin - vs1.topMargin) * p).toInt()
lpChanged = true
}
if (vs1.bottomMargin != vs2.bottomMargin) {
it.bottomMargin = (vs1.bottomMargin + (vs2.bottomMargin - vs1.bottomMargin) * p).toInt()
lpChanged = true
}
if (vs1.leftMargin != vs2.leftMargin) {
it.leftMargin = (vs1.leftMargin + (vs2.leftMargin - vs1.leftMargin) * p).toInt()
lpChanged = true
}
if (vs1.topMargin != vs2.topMargin) {
it.topMargin = (vs1.topMargin + (vs2.topMargin - vs1.topMargin) * p).toInt()
lpChanged = true
}
}
if (lpChanged) layoutParams = o
}
}
}
fun Any?.statesChangeByAnimation(views: Array, tag1: Int, tag2: Int, start: Float = 0F, end: Float = 1F, updateCallback: AnimationUpdateListener? = null, updateStateListener: AnimatorListenerAdapter? = null, duration1: Long = 400L, startDelay1: Long = 0L): ValueAnimator {
return ValueAnimator.ofFloat(start, end).apply {
startDelay = startDelay1
duration = duration1
interpolator = AccelerateDecelerateInterpolator()
addUpdateListener { animation ->
val p = animation.animatedValue as Float
updateCallback?.onAnimationUpdate(tag1, tag2, p)
for (it in views) it.stateRefresh(tag1, tag2, animation.animatedValue as Float)
}
updateStateListener?.let { addListener(it) }
start()
}
}
interface AnimationUpdateListener {
fun onAnimationUpdate(tag1: Int, tag2: Int, p: Float)
}
================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
================================================
FILE: app/src/main/res/drawable/merchant_search_shape.xml
================================================
================================================
FILE: app/src/main/res/drawable/settle_submit_shape.xml
================================================
================================================
FILE: app/src/main/res/drawable/shadow_b_000_shape.xml
================================================
================================================
FILE: app/src/main/res/drawable/shadow_b_fff_shape.xml
================================================
================================================
FILE: app/src/main/res/drawable/tab_title_selector.xml
================================================
================================================
FILE: app/src/main/res/drawable/transparent.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_activity.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_content_layout.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_food_list_content.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_food_list_content_image.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_food_list_recommend.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_food_list_recommend_cell.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_food_list_side.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_food_list_sticky_title.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_food_list_top.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_page_cell_layout.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_page_food_layout.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_page_layout.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_settle_layout.xml
================================================
================================================
FILE: app/src/main/res/layout/merchant_title_layout.xml
================================================
================================================
FILE: app/src/main/res/layout/ticket_view.xml
================================================
================================================
FILE: app/src/main/res/values/frames.xml
================================================
#000
#000
#000
10dp
14.5dp
48dp
38dp
#E5E5E5
202dp
80dp
================================================
FILE: app/src/main/res/values/strings.xml
================================================
behavior-learn
com.example.learn.business.MerchantPageBehavior
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${KOTLIN_VERSION}"
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
maven { url 'https://maven.google.com' }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
support_multidex = 'com.android.support:multidex:1.0.2'
support_support_v4 = "com.android.support:support-v4:${ANDROID_SUPPORT_VERSION}"
support_appcompat_v7 = "com.android.support:appcompat-v7:${ANDROID_SUPPORT_VERSION}"
support_recyclerview_v7 = "com.android.support:recyclerview-v7:${ANDROID_SUPPORT_VERSION}"
support_design = "com.android.support:design:${ANDROID_SUPPORT_VERSION}"
kotlin = "org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN_VERSION}"
kotlin_stdlib = "org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN_VERSION}"
kotlin_anko_common = "org.jetbrains.anko:anko-common:${ANKO_VERSION}"
glide = 'com.github.bumptech.glide:glide:4.6.1'
glide_compiler = 'com.github.bumptech.glide:compiler:4.6.1'
glide_transformations = 'jp.wasabeef:glide-transformations:3.0.1'
list_pull_to_refresh = 'in.srain.cube:ultra-ptr:1.0.11'
list_adapter = 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.40'
eventbus = 'org.greenrobot:eventbus:3.1.1'
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Wed May 30 14:37:50 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
ANDROID_SUPPORT_VERSION=27.0.2
COMPILE_SDK_VERSION=27
TARGET_SDK_VERSION=27
MIN_SDK_VERSION=16
KOTLIN_VERSION=1.1.51
ANKO_VERSION=0.9
APPLICATION_ID=com.example.learn
VERSION_CODE=1
VERSION_NAME=1.0.0
DEBUG=false
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
include ':app'