mirror of
https://github.com/AllanWang/Frost-for-Facebook.git
synced 2024-11-10 04:52:38 +01:00
add progressbar and remove tab indicator
This commit is contained in:
parent
d924fd96dd
commit
266569a14f
@ -121,7 +121,7 @@
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
@ -112,6 +112,8 @@ dependencies {
|
||||
compile("com.mikepenz:materialdrawer:${MATERIAL_DRAWER}@aar") {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
compile 'com.jude:swipebackhelper:3.1.2'
|
||||
}
|
||||
|
||||
kapt {
|
||||
|
@ -87,6 +87,9 @@
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".WebOverlayActivity"
|
||||
android:theme="@style/AppTheme.Overlay" />
|
||||
|
||||
<receiver
|
||||
android:name=".services.NotificationReceiver"
|
||||
|
@ -11,6 +11,7 @@ import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.ViewTreeObserver
|
||||
import butterknife.ButterKnife
|
||||
import com.mikepenz.materialdrawer.Drawer
|
||||
import com.pitchedapps.frost.dbflow.loadFbTabs
|
||||
@ -18,9 +19,7 @@ import com.pitchedapps.frost.dbflow.saveAsync
|
||||
import com.pitchedapps.frost.facebook.FbTab
|
||||
import com.pitchedapps.frost.fragments.BaseFragment
|
||||
import com.pitchedapps.frost.fragments.WebFragment
|
||||
import com.pitchedapps.frost.utils.Changelog
|
||||
import com.pitchedapps.frost.utils.bindView
|
||||
import com.pitchedapps.frost.utils.toDrawable
|
||||
import com.pitchedapps.frost.utils.*
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
@ -33,6 +32,8 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// SwipeBackHelper.onCreate(this)
|
||||
// SwipeBackHelper.getCurrentPage(this).setSwipeBackEnable(false)
|
||||
setContentView(R.layout.activity_main)
|
||||
ButterKnife.bind(this)
|
||||
setSupportActionBar(toolbar)
|
||||
@ -40,6 +41,20 @@ class MainActivity : AppCompatActivity() {
|
||||
adapter = SectionsPagerAdapter(supportFragmentManager, loadFbTabs())
|
||||
viewPager.adapter = adapter
|
||||
viewPager.offscreenPageLimit = 5
|
||||
viewPager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
|
||||
val delta: Float by lazy { positionOffset * (255 - 128).toFloat() }
|
||||
(0 until tabs.tabCount).asSequence().forEach {
|
||||
i ->
|
||||
tabs.getTabAt(i)?.icon?.alpha = when (i) {
|
||||
position -> (255.0 - delta).toInt()
|
||||
position + 1 -> (128.0 + delta).toInt()
|
||||
else -> 128
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
setupTabs()
|
||||
fab.setOnClickListener { view ->
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
@ -47,6 +62,17 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
// SwipeBackHelper.onPostCreate(this)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// SwipeBackHelper.onDestroy(this)
|
||||
}
|
||||
|
||||
fun setupTabs() {
|
||||
|
||||
viewPager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabs))
|
||||
@ -72,8 +98,7 @@ class MainActivity : AppCompatActivity() {
|
||||
// finish()
|
||||
}
|
||||
R.id.action_changelog -> Changelog.show(this)
|
||||
R.id.action_call -> {
|
||||
}
|
||||
R.id.action_call -> WebOverlayActivity.newInstance(this, "https://www.google.ca")
|
||||
R.id.action_db -> adapter.pages.saveAsync(this)
|
||||
R.id.action_restart -> {
|
||||
finish();
|
||||
|
@ -3,12 +3,17 @@ package com.pitchedapps.frost
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.ActivityOptionsCompat
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.widget.SwipeRefreshLayout
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import butterknife.ButterKnife
|
||||
import com.jude.swipbackhelper.SwipeBackHelper
|
||||
import com.pitchedapps.frost.utils.bindView
|
||||
import com.pitchedapps.frost.web.FrostWebView
|
||||
import com.pitchedapps.frost.web.FrostWebViewCore
|
||||
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-06-01.
|
||||
@ -16,15 +21,15 @@ import com.pitchedapps.frost.web.FrostWebView
|
||||
class WebOverlayActivity : AppCompatActivity() {
|
||||
|
||||
val toolbar: Toolbar by bindView(R.id.toolbar)
|
||||
val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh)
|
||||
val web: FrostWebView by bindView(R.id.frost_webview)
|
||||
val frostWeb:FrostWebView by bindView(R.id.frost_webview)
|
||||
|
||||
companion object {
|
||||
private const val ARG_URL = "arg_url"
|
||||
fun newInstance(context: Context, url: String) {
|
||||
val intent = Intent(context, WebOverlayActivity::class.java)
|
||||
intent.putExtra(ARG_URL, url)
|
||||
context.startActivity(intent)
|
||||
val bundle = ActivityOptionsCompat.makeCustomAnimation(context, R.anim.slide_in_right, R.anim.slide_out_right).toBundle()
|
||||
ContextCompat.startActivity(context, intent, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,5 +38,23 @@ class WebOverlayActivity : AppCompatActivity() {
|
||||
setContentView(R.layout.activity_web_overlay)
|
||||
ButterKnife.bind(this)
|
||||
setSupportActionBar(toolbar)
|
||||
frostWeb.baseUrl = intent.extras.getString(ARG_URL)
|
||||
SwipeBackHelper.onCreate(this)
|
||||
SwipeBackHelper.getCurrentPage(this)
|
||||
.setSwipeBackEnable(true)
|
||||
.setSwipeSensitivity(0.5f)
|
||||
.setSwipeRelateEnable(true)
|
||||
.setSwipeRelateOffset(300)
|
||||
}
|
||||
|
||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
SwipeBackHelper.onPostCreate(this)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
SwipeBackHelper.onDestroy(this)
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.pitchedapps.frost.events
|
||||
|
||||
import com.pitchedapps.frost.web.FrostWebView
|
||||
import com.pitchedapps.frost.web.FrostWebViewCore
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-31.
|
||||
@ -12,7 +12,7 @@ class WebEvent(val key: Int, val urlMatch: String? = null) {
|
||||
const val REFRESH_BASE = 1
|
||||
}
|
||||
|
||||
fun execute(webView: FrostWebView) {
|
||||
fun execute(webView: FrostWebViewCore) {
|
||||
if (urlMatch != null && !webView.url.contains(urlMatch)) return
|
||||
when (key) {
|
||||
REFRESH -> webView.reload()
|
||||
|
@ -5,34 +5,26 @@ import android.support.v4.widget.SwipeRefreshLayout
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import butterknife.ButterKnife
|
||||
import butterknife.Unbinder
|
||||
import com.pitchedapps.frost.R
|
||||
import com.pitchedapps.frost.utils.bindView
|
||||
import com.pitchedapps.frost.utils.putString
|
||||
import com.pitchedapps.frost.web.FrostWebView
|
||||
import com.pitchedapps.frost.web.WebStatus
|
||||
import com.pitchedapps.frost.web.FrostWebViewCore
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-29.
|
||||
*/
|
||||
|
||||
|
||||
class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
override fun onRefresh() {
|
||||
web.reload()
|
||||
}
|
||||
class WebFragment : BaseFragment() {
|
||||
|
||||
companion object {
|
||||
private const val ARG_URL = "arg_url"
|
||||
fun newInstance(position: Int, url: String) = BaseFragment.newInstance(WebFragment(), position).putString(ARG_URL, url)
|
||||
}
|
||||
|
||||
val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh)
|
||||
val web: FrostWebView by bindView(R.id.frost_webview)
|
||||
val refresh: SwipeRefreshLayout by lazy { frostWebView.refresh }
|
||||
val web: FrostWebViewCore by lazy { frostWebView.web }
|
||||
lateinit var url: String
|
||||
private lateinit var unbinder: Unbinder
|
||||
lateinit private var frostWebView: FrostWebView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -41,39 +33,10 @@ class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
val view = inflater.inflate(R.layout.swipe_webview, container, false)
|
||||
unbinder = ButterKnife.bind(this, view)
|
||||
return view
|
||||
frostWebView = FrostWebView(context)
|
||||
frostWebView.baseUrl = url
|
||||
return frostWebView
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
web.baseUrl = url
|
||||
web.observable.subscribe {
|
||||
t: WebStatus ->
|
||||
when (t) {
|
||||
WebStatus.LOADED, WebStatus.ERROR -> refresh.isRefreshing = false
|
||||
WebStatus.LOADING -> refresh.isRefreshing = true
|
||||
}
|
||||
}
|
||||
refresh.setOnRefreshListener(this)
|
||||
// refresh.shouldSwipe = {
|
||||
// L.e("Y ${web.scrollY}")
|
||||
// SwipeRefreshBase.shouldScroll(web)
|
||||
// }
|
||||
web.loadUrl(url)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
unbinder.unbind()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (web.canGoBack()) {
|
||||
web.goBack()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
override fun onBackPressed() = frostWebView.onBackPressed()
|
||||
}
|
@ -1,13 +1,19 @@
|
||||
package com.pitchedapps.frost.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.support.annotation.ColorRes
|
||||
import android.support.annotation.ColorInt
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-29.
|
||||
*/
|
||||
fun IIcon.toDrawable(c: Context, sizeDp: Int = 24, @ColorRes color: Int = android.R.color.white): Drawable
|
||||
= IconicsDrawable(c).icon(this).colorRes(color).sizeDp(sizeDp)
|
||||
fun IIcon.toDrawable(c: Context, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE): Drawable {
|
||||
val state = ColorStateList.valueOf(color)
|
||||
val icon = IconicsDrawable(c).icon(this).sizeDp(sizeDp)
|
||||
icon.setTintList(state)
|
||||
return icon
|
||||
}
|
@ -6,7 +6,7 @@ import io.reactivex.subjects.Subject
|
||||
* Created by Allan Wang on 2017-05-29.
|
||||
*/
|
||||
interface ObservableContainer<T> {
|
||||
val observable: Subject<T>
|
||||
val progressObservable: Subject<T>
|
||||
}
|
||||
|
||||
interface KeyPairObservable : ObservableContainer<Pair<Int, Int>>
|
107
app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt
Normal file
107
app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt
Normal file
@ -0,0 +1,107 @@
|
||||
package com.pitchedapps.frost.views
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.view.View
|
||||
import android.view.ViewAnimationUtils
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-06-01.
|
||||
*/
|
||||
|
||||
fun View.rootCircularReveal(x: Int = 0, y: Int = 0, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) {
|
||||
this.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
|
||||
override fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int,
|
||||
oldRight: Int, oldBottom: Int) {
|
||||
v.removeOnLayoutChangeListener(this)
|
||||
var x2 = x
|
||||
var y2 = y
|
||||
if (x2 > right) x2 = 0
|
||||
if (y2 > bottom) y2 = 0
|
||||
val radius = Math.hypot(Math.max(x2, right - x2).toDouble(), Math.max(y2, bottom - y2).toDouble()).toInt()
|
||||
val reveal = ViewAnimationUtils.createCircularReveal(v, x2, y2, 0f, radius.toFloat())
|
||||
reveal.interpolator = DecelerateInterpolator(1f)
|
||||
reveal.duration = duration
|
||||
reveal.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
visibility = View.VISIBLE
|
||||
onStart?.invoke()
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit
|
||||
override fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit
|
||||
})
|
||||
reveal.start()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) {
|
||||
if (!isAttachedToWindow) {
|
||||
visibility = View.VISIBLE
|
||||
return
|
||||
}
|
||||
var r = radius
|
||||
if (r < 0.0f) {
|
||||
r = Math.max(Math.hypot(x.toDouble(), y.toDouble()), Math.hypot((width - x.toDouble()), (height - y.toDouble()))).toFloat()
|
||||
}
|
||||
val anim = ViewAnimationUtils.createCircularReveal(this, x, y, 0f, r).setDuration(duration)
|
||||
anim.startDelay = offset
|
||||
anim.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
visibility = View.VISIBLE
|
||||
onStart?.invoke()
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit
|
||||
override fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit
|
||||
})
|
||||
anim.start()
|
||||
}
|
||||
|
||||
fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) {
|
||||
if (!isAttachedToWindow) {
|
||||
visibility = View.VISIBLE
|
||||
return
|
||||
}
|
||||
if (isAttachedToWindow) {
|
||||
val anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in)
|
||||
anim.startOffset = offset
|
||||
anim.duration = duration
|
||||
anim.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(animation: Animation?) {}
|
||||
override fun onAnimationEnd(animation: Animation?) = onFinish?.invoke() ?: Unit
|
||||
override fun onAnimationStart(animation: Animation?) {
|
||||
visibility = View.VISIBLE
|
||||
onStart?.invoke()
|
||||
}
|
||||
})
|
||||
startAnimation(anim)
|
||||
}
|
||||
}
|
||||
|
||||
fun View.fadeOut(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) {
|
||||
if (!isAttachedToWindow) {
|
||||
visibility = View.INVISIBLE
|
||||
return
|
||||
}
|
||||
val anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out)
|
||||
anim.startOffset = offset
|
||||
anim.duration = duration
|
||||
anim.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(animation: Animation?) {}
|
||||
override fun onAnimationEnd(animation: Animation?) {
|
||||
visibility = View.INVISIBLE
|
||||
onFinish?.invoke()
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animation?) {
|
||||
onStart?.invoke()
|
||||
}
|
||||
})
|
||||
startAnimation(anim)
|
||||
}
|
@ -1,14 +1,30 @@
|
||||
package com.pitchedapps.frost.views
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.PorterDuff
|
||||
import android.support.annotation.ColorInt
|
||||
import android.support.annotation.ColorRes
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ProgressBar
|
||||
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-31.
|
||||
*/
|
||||
fun View.matchParent() {
|
||||
with (layoutParams) {
|
||||
with(layoutParams) {
|
||||
height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
}
|
||||
|
||||
fun ProgressBar.tintRes(@ColorRes id: Int) = tint(ContextCompat.getColor(context, id))
|
||||
|
||||
fun ProgressBar.tint(@ColorInt color: Int) {
|
||||
val sl = ColorStateList.valueOf(color)
|
||||
progressTintList = sl
|
||||
secondaryProgressTintList = sl
|
||||
indeterminateTintList = sl
|
||||
}
|
@ -2,14 +2,28 @@ package com.pitchedapps.frost.web
|
||||
|
||||
import android.webkit.ConsoleMessage
|
||||
import android.webkit.WebChromeClient
|
||||
import android.webkit.WebView
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import io.reactivex.subjects.Subject
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-31.
|
||||
*/
|
||||
class FrostChromeClient:WebChromeClient() {
|
||||
class FrostChromeClient(val progressObservable: Subject<Int>) : WebChromeClient() {
|
||||
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
|
||||
L.d("Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}")
|
||||
return super.onConsoleMessage(consoleMessage)
|
||||
}
|
||||
|
||||
override fun onReceivedTitle(view: WebView?, title: String?) {
|
||||
super.onReceivedTitle(view, title)
|
||||
L.d("Title $title")
|
||||
}
|
||||
|
||||
override fun onProgressChanged(view: WebView, newProgress: Int) {
|
||||
super.onProgressChanged(view, newProgress)
|
||||
progressObservable.onNext(newProgress)
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.pitchedapps.frost.web
|
||||
|
||||
enum class FrostWebEnums {
|
||||
LOADING, LOADED, ERROR
|
||||
}
|
||||
|
||||
enum class FrostWebOverlay(val match: String) {
|
||||
STORY("story.php?story_fbid");
|
||||
|
||||
companion object {
|
||||
val values = values()
|
||||
}
|
||||
}
|
@ -1,141 +1,62 @@
|
||||
package com.pitchedapps.frost.web
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.support.v4.view.MotionEventCompat
|
||||
import android.support.v4.view.NestedScrollingChild
|
||||
import android.support.v4.view.NestedScrollingChildHelper
|
||||
import android.support.v4.view.ViewCompat
|
||||
import android.os.Build
|
||||
import android.support.v4.widget.SwipeRefreshLayout
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.webkit.WebView
|
||||
import com.pitchedapps.frost.events.WebEvent
|
||||
import com.pitchedapps.frost.utils.ObservableContainer
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import io.reactivex.subjects.Subject
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
|
||||
enum class WebStatus {
|
||||
LOADING, LOADED, ERROR
|
||||
}
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ProgressBar
|
||||
import butterknife.ButterKnife
|
||||
import com.pitchedapps.frost.R
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import com.pitchedapps.frost.utils.bindView
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-29.
|
||||
*
|
||||
* Courtesy of takahirom
|
||||
*
|
||||
* https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java
|
||||
* Created by Allan Wang on 2017-06-01.
|
||||
*/
|
||||
class FrostWebView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : WebView(context, attrs, defStyleAttr), NestedScrollingChild, ObservableContainer<WebStatus> {
|
||||
|
||||
private val childHelper = NestedScrollingChildHelper(this)
|
||||
private var lastY: Int = 0
|
||||
private val scrollOffset = IntArray(2)
|
||||
private val scrollConsumed = IntArray(2)
|
||||
private var nestedOffsetY: Int = 0
|
||||
override val observable: Subject<WebStatus> //TODO see if we need this
|
||||
var baseUrl: String? = null
|
||||
class FrostWebView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0)
|
||||
: FrameLayout(context, attrs, defStyleAttr, defStyleRes), SwipeRefreshLayout.OnRefreshListener {
|
||||
var baseUrl: String?
|
||||
get() = web.baseUrl
|
||||
set(value) {
|
||||
web.baseUrl = value
|
||||
if (value != null) web.loadUrl(value)
|
||||
}
|
||||
val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh)
|
||||
val web: FrostWebViewCore by bindView(R.id.frost_webview_core)
|
||||
val progress: ProgressBar by bindView(R.id.progressBar)
|
||||
|
||||
init {
|
||||
isNestedScrollingEnabled = true
|
||||
observable = BehaviorSubject.create<WebStatus>()
|
||||
setupWebview()
|
||||
inflate(getContext(), R.layout.swipe_webview, this)
|
||||
ButterKnife.bind(this)
|
||||
web.progressObservable.observeOn(AndroidSchedulers.mainThread()).subscribe {
|
||||
val loaded = it == 100
|
||||
refresh.isRefreshing = !loaded
|
||||
progress.visibility = if (loaded) View.INVISIBLE else View.VISIBLE
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) progress.setProgress(it, true)
|
||||
else progress.progress = it
|
||||
}
|
||||
refresh.setOnRefreshListener(this)
|
||||
addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
|
||||
override fun onViewDetachedFromWindow(v: View) {
|
||||
web.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
fun setupWebview() {
|
||||
settings.javaScriptEnabled = true
|
||||
settings.domStorageEnabled = true
|
||||
setLayerType(View.LAYER_TYPE_HARDWARE, null)
|
||||
setWebViewClient(FrostWebViewClient(observable))
|
||||
setWebChromeClient(FrostChromeClient())
|
||||
override fun onViewAttachedToWindow(v: View) {}
|
||||
})
|
||||
}
|
||||
|
||||
override fun loadUrl(url: String?) {
|
||||
if (url != null)
|
||||
super.loadUrl(url)
|
||||
override fun onRefresh() {
|
||||
web.reload()
|
||||
}
|
||||
|
||||
override fun onTouchEvent(ev: MotionEvent): Boolean {
|
||||
val event = MotionEvent.obtain(ev)
|
||||
val action = MotionEventCompat.getActionMasked(event)
|
||||
if (action == MotionEvent.ACTION_DOWN)
|
||||
nestedOffsetY = 0
|
||||
val eventY = event.y.toInt()
|
||||
event.offsetLocation(0f, nestedOffsetY.toFloat())
|
||||
val returnValue: Boolean
|
||||
when (action) {
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
var deltaY = lastY - eventY
|
||||
// NestedPreScroll
|
||||
if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) {
|
||||
deltaY -= scrollConsumed[1]
|
||||
event.offsetLocation(0f, -scrollOffset[1].toFloat())
|
||||
nestedOffsetY += scrollOffset[1]
|
||||
fun onBackPressed(): Boolean {
|
||||
if (web.canGoBack()) {
|
||||
web.goBack()
|
||||
return true
|
||||
}
|
||||
lastY = eventY - scrollOffset[1]
|
||||
returnValue = super.onTouchEvent(event)
|
||||
// NestedScroll
|
||||
if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) {
|
||||
event.offsetLocation(0f, scrollOffset[1].toFloat())
|
||||
nestedOffsetY += scrollOffset[1]
|
||||
lastY -= scrollOffset[1]
|
||||
return false
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
returnValue = super.onTouchEvent(event)
|
||||
lastY = eventY
|
||||
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
returnValue = super.onTouchEvent(event)
|
||||
stopNestedScroll()
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
EventBus.getDefault().unregister(this)
|
||||
super.onDetachedFromWindow()
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun webEvent(event: WebEvent) = event.execute(this)
|
||||
|
||||
// Nested Scroll implements
|
||||
override fun setNestedScrollingEnabled(enabled: Boolean) {
|
||||
childHelper.isNestedScrollingEnabled = enabled
|
||||
}
|
||||
|
||||
override fun isNestedScrollingEnabled() = childHelper.isNestedScrollingEnabled
|
||||
|
||||
override fun startNestedScroll(axes: Int) = childHelper.startNestedScroll(axes)
|
||||
|
||||
override fun stopNestedScroll() = childHelper.stopNestedScroll()
|
||||
|
||||
override fun hasNestedScrollingParent() = childHelper.hasNestedScrollingParent()
|
||||
|
||||
override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?)
|
||||
= childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
|
||||
|
||||
override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?)
|
||||
= childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
|
||||
|
||||
override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean)
|
||||
= childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
|
||||
|
||||
override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float)
|
||||
= childHelper.dispatchNestedPreFling(velocityX, velocityY)
|
||||
|
||||
}
|
@ -1,18 +1,20 @@
|
||||
package com.pitchedapps.frost.web
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.view.View
|
||||
import android.view.KeyEvent
|
||||
import android.webkit.*
|
||||
import com.pitchedapps.frost.facebook.FACEBOOK_COM
|
||||
import com.pitchedapps.frost.facebook.FbCookie
|
||||
import com.pitchedapps.frost.injectors.CssAssets
|
||||
import com.pitchedapps.frost.utils.L
|
||||
import com.pitchedapps.frost.views.circularReveal
|
||||
import com.pitchedapps.frost.views.fadeOut
|
||||
import io.reactivex.subjects.Subject
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-31.
|
||||
*/
|
||||
class FrostWebViewClient(val observable: Subject<WebStatus>) : WebViewClient() {
|
||||
class FrostWebViewClient : WebViewClient() {
|
||||
|
||||
companion object {
|
||||
//Collections of jewels mapped with url match -> id
|
||||
@ -23,31 +25,50 @@ class FrostWebViewClient(val observable: Subject<WebStatus>) : WebViewClient() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
|
||||
super.onReceivedError(view, request, error)
|
||||
observable.onNext(WebStatus.ERROR)
|
||||
L.e("FWV Error ${request}")
|
||||
}
|
||||
|
||||
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
|
||||
super.onPageStarted(view, url, favicon)
|
||||
observable.onNext(WebStatus.LOADING)
|
||||
L.d("FWV Loading $url")
|
||||
if (!url.contains(FACEBOOK_COM)) return
|
||||
if (url.contains("logout.php")) FbCookie.logout()
|
||||
view.visibility = View.INVISIBLE
|
||||
view.fadeOut(duration = 200L)
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView, url: String) {
|
||||
super.onPageFinished(view, url)
|
||||
if (!url.contains(FACEBOOK_COM)) return
|
||||
observable.onNext(WebStatus.LOADED)
|
||||
FbCookie.checkUserId(url, CookieManager.getInstance().getCookie(url))
|
||||
CssAssets.BASE.inject(view, {
|
||||
view.visibility = View.VISIBLE
|
||||
view.circularReveal(offset = 150L)
|
||||
})
|
||||
}
|
||||
|
||||
override fun shouldOverrideKeyEvent(view: WebView, event: KeyEvent): Boolean {
|
||||
L.d("Key event ${event.keyCode}")
|
||||
return super.shouldOverrideKeyEvent(view, event)
|
||||
}
|
||||
|
||||
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
||||
L.d("Hi")
|
||||
L.d("Url Loading ${request.url?.path}")
|
||||
return super.shouldOverrideUrlLoading(view, request)
|
||||
}
|
||||
|
||||
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
||||
if (!request.url.host.contains(FACEBOOK_COM)) return super.shouldInterceptRequest(view, request)
|
||||
L.d("Url intercept ${request.url.path}")
|
||||
return super.shouldInterceptRequest(view, request)
|
||||
}
|
||||
|
||||
override fun onLoadResource(view: WebView, url: String) {
|
||||
if (!url.contains(FACEBOOK_COM)) return super.onLoadResource(view, url)
|
||||
L.d("Resource $url")
|
||||
FrostWebOverlay.values.forEach {
|
||||
if (url.contains(it.match))
|
||||
L.d("Loaded $it")
|
||||
}
|
||||
super.onLoadResource(view, url)
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,137 @@
|
||||
package com.pitchedapps.frost.web
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.support.v4.view.MotionEventCompat
|
||||
import android.support.v4.view.NestedScrollingChild
|
||||
import android.support.v4.view.NestedScrollingChildHelper
|
||||
import android.support.v4.view.ViewCompat
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.webkit.WebView
|
||||
import com.pitchedapps.frost.events.WebEvent
|
||||
import com.pitchedapps.frost.utils.ObservableContainer
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import io.reactivex.subjects.Subject
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-29.
|
||||
*
|
||||
* Courtesy of takahirom
|
||||
*
|
||||
* https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java
|
||||
*/
|
||||
class FrostWebViewCore @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : WebView(context, attrs, defStyleAttr), NestedScrollingChild, ObservableContainer<Int> {
|
||||
|
||||
private val childHelper = NestedScrollingChildHelper(this)
|
||||
private var lastY: Int = 0
|
||||
private val scrollOffset = IntArray(2)
|
||||
private val scrollConsumed = IntArray(2)
|
||||
private var nestedOffsetY: Int = 0
|
||||
override val progressObservable: Subject<Int> //TODO see if we need this
|
||||
var baseUrl: String? = null
|
||||
|
||||
init {
|
||||
isNestedScrollingEnabled = true
|
||||
progressObservable = BehaviorSubject.create<Int>()
|
||||
setupWebview()
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
fun setupWebview() {
|
||||
settings.javaScriptEnabled = true
|
||||
settings.domStorageEnabled = true
|
||||
setLayerType(View.LAYER_TYPE_HARDWARE, null)
|
||||
setWebViewClient(FrostWebViewClient())
|
||||
setWebChromeClient(FrostChromeClient(progressObservable))
|
||||
}
|
||||
|
||||
override fun loadUrl(url: String?) {
|
||||
if (url != null)
|
||||
super.loadUrl(url)
|
||||
}
|
||||
|
||||
override fun onTouchEvent(ev: MotionEvent): Boolean {
|
||||
val event = MotionEvent.obtain(ev)
|
||||
val action = MotionEventCompat.getActionMasked(event)
|
||||
if (action == MotionEvent.ACTION_DOWN)
|
||||
nestedOffsetY = 0
|
||||
val eventY = event.y.toInt()
|
||||
event.offsetLocation(0f, nestedOffsetY.toFloat())
|
||||
val returnValue: Boolean
|
||||
when (action) {
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
var deltaY = lastY - eventY
|
||||
// NestedPreScroll
|
||||
if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) {
|
||||
deltaY -= scrollConsumed[1]
|
||||
event.offsetLocation(0f, -scrollOffset[1].toFloat())
|
||||
nestedOffsetY += scrollOffset[1]
|
||||
}
|
||||
lastY = eventY - scrollOffset[1]
|
||||
returnValue = super.onTouchEvent(event)
|
||||
// NestedScroll
|
||||
if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) {
|
||||
event.offsetLocation(0f, scrollOffset[1].toFloat())
|
||||
nestedOffsetY += scrollOffset[1]
|
||||
lastY -= scrollOffset[1]
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
returnValue = super.onTouchEvent(event)
|
||||
lastY = eventY
|
||||
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
returnValue = super.onTouchEvent(event)
|
||||
stopNestedScroll()
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
EventBus.getDefault().unregister(this)
|
||||
super.onDetachedFromWindow()
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun webEvent(event: WebEvent) = event.execute(this)
|
||||
|
||||
// Nested Scroll implements
|
||||
override fun setNestedScrollingEnabled(enabled: Boolean) {
|
||||
childHelper.isNestedScrollingEnabled = enabled
|
||||
}
|
||||
|
||||
override fun isNestedScrollingEnabled() = childHelper.isNestedScrollingEnabled
|
||||
|
||||
override fun startNestedScroll(axes: Int) = childHelper.startNestedScroll(axes)
|
||||
|
||||
override fun stopNestedScroll() = childHelper.stopNestedScroll()
|
||||
|
||||
override fun hasNestedScrollingParent() = childHelper.hasNestedScrollingParent()
|
||||
|
||||
override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?)
|
||||
= childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
|
||||
|
||||
override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?)
|
||||
= childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
|
||||
|
||||
override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean)
|
||||
= childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
|
||||
|
||||
override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float)
|
||||
= childHelper.dispatchNestedPreFling(velocityX, velocityY)
|
||||
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package com.pitchedapps.frost.web
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v4.widget.SwipeRefreshLayout
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.webkit.WebView
|
||||
import com.pitchedapps.frost.utils.Utils
|
||||
|
||||
|
||||
/**
|
||||
* Created by Allan Wang on 2017-05-28.
|
||||
*/
|
||||
class SwipeRefreshBase @JvmOverloads constructor(
|
||||
context: Context?, attrs: AttributeSet? = null
|
||||
) : SwipeRefreshLayout(context, attrs) {
|
||||
|
||||
lateinit var shouldSwipe: (ev: MotionEvent) -> Boolean
|
||||
|
||||
companion object {
|
||||
private val SCROLL_BUFFER by lazy { Utils.dpToPx(5) }
|
||||
fun shouldScroll(webview: WebView) = webview.scrollY <= SCROLL_BUFFER
|
||||
}
|
||||
|
||||
// override fun onInterceptTouchEvent(ev: MotionEvent):Boolean {
|
||||
// val b = shouldSwipe.invoke(ev) && super.onInterceptTouchEvent(ev)
|
||||
// L.e("Should swipe $b")
|
||||
// return b
|
||||
// }
|
||||
}
|
7
app/src/main/res/anim/slide_in_right.xml
Normal file
7
app/src/main/res/anim/slide_in_right.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="@android:integer/config_shortAnimTime"
|
||||
android:fromXDelta="100%p"
|
||||
android:toXDelta="0" />
|
||||
</set>
|
7
app/src/main/res/anim/slide_out_right.xml
Normal file
7
app/src/main/res/anim/slide_out_right.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="@android:integer/config_shortAnimTime"
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="100%p" />
|
||||
</set>
|
@ -1,18 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main_content"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true" tools:context=".MainActivity">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout android:id="@+id/appbar"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/appbar_padding_top"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<android.support.v7.widget.Toolbar android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways"
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay">
|
||||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
@ -20,17 +28,23 @@
|
||||
<android.support.design.widget.TabLayout
|
||||
android:id="@+id/tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
app:tabIndicatorHeight="0dp" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<android.support.v4.view.ViewPager android:id="@+id/container"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<android.support.design.widget.FloatingActionButton android:id="@+id/fab"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin"
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:srcCompat="@android:drawable/ic_dialog_email" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
@ -16,6 +16,9 @@
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
<include layout="@layout/swipe_webview" />
|
||||
<com.pitchedapps.frost.web.FrostWebView
|
||||
android:id="@+id/frost_webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
@ -1,15 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.pitchedapps.frost.web.FrostWebView
|
||||
android:id="@+id/frost_webview"
|
||||
<com.pitchedapps.frost.web.FrostWebViewCore
|
||||
android:id="@+id/frost_webview_core"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="@style/FrostProgressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top" />
|
||||
</FrameLayout>
|
@ -8,5 +8,6 @@
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
<dimen name="appbar_padding_top">8dp</dimen>
|
||||
<dimen name="splash_logo">16dp</dimen>
|
||||
<dimen name="progress_bar_height">1dip</dimen>
|
||||
|
||||
</resources>
|
||||
|
@ -11,6 +11,13 @@
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
<style name="AppTheme.Overlay" parent="AppTheme.NoActionBar">
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item>
|
||||
<item name="android:activityOpenExitAnimation">@anim/slide_out_right</item>
|
||||
<item name="android:activityCloseEnterAnimation">@anim/slide_in_right</item>
|
||||
<item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
|
||||
</style>
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
@ -20,4 +27,9 @@
|
||||
<item name="colorPrimaryDark">@color/splashBackground</item>
|
||||
<item name="colorAccent">@color/splashBackground</item>
|
||||
</style>
|
||||
|
||||
<style name="FrostProgressBar" parent="Widget.AppCompat.ProgressBar.Horizontal">
|
||||
<item name="android:minHeight">@dimen/progress_bar_height</item>
|
||||
<item name="android:maxHeight">@dimen/progress_bar_height</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user