First run screen is functional
This commit is contained in:
parent
9a45b5e242
commit
6a8cc9bc6c
Binary file not shown.
|
@ -85,10 +85,10 @@ internal object SynchronizerModule {
|
|||
|
||||
// TODO: load most of these properties in later, perhaps from settings
|
||||
object Properties {
|
||||
const val COMPACT_BLOCK_SERVER = "10.0.2.2"
|
||||
// const val COMPACT_BLOCK_SERVER = "lightwalletd.z.cash"
|
||||
// const val COMPACT_BLOCK_SERVER = "10.0.0.26"
|
||||
const val COMPACT_BLOCK_SERVER = "lightwalletd.z.cash"
|
||||
const val COMPACT_BLOCK_PORT = 9067
|
||||
const val CACHE_DB_NAME = "wallet_cache.db"
|
||||
const val DATA_DB_NAME = "wallet_data.db"
|
||||
const val CACHE_DB_NAME = "wallet_cache9.db"
|
||||
const val DATA_DB_NAME = "wallet_data9.db"
|
||||
val SEED_PROVIDER = SampleSeedProvider("dummyseed")
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package cash.z.android.wallet.ui.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import dagger.android.AndroidInjection
|
||||
import dagger.android.AndroidInjector
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasFragmentInjector
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import dagger.android.support.HasSupportFragmentInjector
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
abstract class BaseMainActivity : DaggerAppCompatActivity(), CoroutineScope, HasFragmentInjector,
|
||||
HasSupportFragmentInjector {
|
||||
private lateinit var job: Job
|
||||
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var supportFragmentInjector: DispatchingAndroidInjector<Fragment>
|
||||
@Inject
|
||||
lateinit var frameworkFragmentInjector: DispatchingAndroidInjector<android.app.Fragment>
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
job = Job()
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun supportFragmentInjector(): AndroidInjector<androidx.fragment.app.Fragment>? {
|
||||
return supportFragmentInjector
|
||||
}
|
||||
|
||||
override fun fragmentInjector(): AndroidInjector<android.app.Fragment>? {
|
||||
return frameworkFragmentInjector
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package cash.z.android.wallet.ui.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
|
@ -23,7 +25,14 @@ import dagger.android.support.DaggerAppCompatActivity
|
|||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.nav_header_main.*
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.android.AndroidInjection
|
||||
import kotlinx.android.synthetic.main.activity_main_first_run.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainActivity : BaseActivity() {
|
||||
|
|
|
@ -14,6 +14,7 @@ import androidx.annotation.ColorRes
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.transition.Transition
|
||||
|
@ -39,6 +40,9 @@ import kotlinx.android.synthetic.main.include_home_header.*
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlin.random.Random
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.activity_main_first_run.*
|
||||
import kotlin.random.nextLong
|
||||
|
||||
|
||||
/**
|
||||
|
@ -75,11 +79,7 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
// setActiveTransactionsShown(false)
|
||||
|
||||
(activity as MainActivity).let { mainActivity ->
|
||||
mainActivity.setSupportActionBar(home_toolbar)
|
||||
mainActivity.setupNavigation()
|
||||
mainActivity.supportActionBar?.setTitle(R.string.destination_title_home)
|
||||
}
|
||||
|
||||
headerFullViews = arrayOf(text_balance_usd, text_balance_includes_info, text_balance_zec, image_zec_symbol_balance_shadow, image_zec_symbol_balance)
|
||||
headerEmptyViews = arrayOf(text_balance_zec_info, text_balance_zec_empty, image_zec_symbol_balance_shadow_empty, image_zec_symbol_balance_empty)
|
||||
|
||||
|
@ -89,23 +89,44 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
group_empty_view_items.visibility = View.GONE
|
||||
group_full_view_items.visibility = View.GONE
|
||||
|
||||
if (MainActivity.DEV_MODE) {
|
||||
image_logo.setOnClickListener {
|
||||
if (MainActivity.DEV_MODE) {
|
||||
mainActivity.navController.navigate(R.id.nav_send_fragment)
|
||||
// forceRedraw()
|
||||
// toggleViews(false)
|
||||
|
||||
} else {
|
||||
forceRedraw()
|
||||
toggleViews(false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
button_active_transaction_cancel.setOnClickListener {
|
||||
onCancelActiveTransaction()
|
||||
}
|
||||
|
||||
refresh_layout.setOnRefreshListener {
|
||||
val fauxRefresh = Random.nextLong(750L..3000L)
|
||||
refresh_layout.postDelayed({
|
||||
refresh_layout.isRefreshing = false
|
||||
}, fauxRefresh)
|
||||
}
|
||||
|
||||
if (mainActivity.synchronizer.processor.dataDbExists) {
|
||||
container_first_run.visibility = View.GONE
|
||||
mainActivity.findViewById<DrawerLayout>(R.id.drawer_layout).setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||
sd_fab.visibility = View.VISIBLE
|
||||
} else {
|
||||
container_first_run.visibility = View.VISIBLE
|
||||
mainActivity.findViewById<DrawerLayout>(R.id.drawer_layout).setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
||||
sd_fab.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
val isEmpty = (recycler_transactions?.adapter?.itemCount ?: 0).let { it == 0 }
|
||||
// val isEmpty = (recycler_transactions?.adapter?.itemCount ?: 0).let { it == 0 }
|
||||
// Log.e("TWIG-t", "Resuming and isEmpty == $isEmpty")
|
||||
// toggleViews(isEmpty)
|
||||
|
||||
|
@ -121,6 +142,12 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
(activity as MainActivity).let { mainActivity ->
|
||||
mainActivity.setSupportActionBar(home_toolbar)
|
||||
mainActivity.setupNavigation()
|
||||
mainActivity.supportActionBar?.setTitle(R.string.destination_title_home)
|
||||
}
|
||||
|
||||
homePresenter = HomePresenter(this, mainActivity.synchronizer)
|
||||
initFab(activity!!)
|
||||
|
||||
|
@ -175,6 +202,12 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
snackbar?.setText(message)
|
||||
if(progress == 100 && snackbar?.isShownOrQueued != true) snackbar?.show()
|
||||
}
|
||||
|
||||
if (progress >= 100) {
|
||||
container_first_run.visibility = View.GONE
|
||||
mainActivity.findViewById<DrawerLayout>(R.id.drawer_layout).setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||
sd_fab.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun setActiveTransactions(activeTransactionMap: Map<ActiveTransaction, TransactionState>) {
|
||||
|
@ -206,6 +239,8 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
button_active_transaction_cancel.text = "${transaction.value/1000L}"
|
||||
}
|
||||
is TransactionState.Failure -> {
|
||||
lottie_active_transaction.setAnimation(R.raw.lottie_send_failure)
|
||||
lottie_active_transaction.playAnimation()
|
||||
title = "Failed"
|
||||
subtitle = when(transactionState.failedStep) {
|
||||
TransactionState.Creating -> "Failed to create transaction"
|
||||
|
@ -216,8 +251,14 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
onCancelActiveTransaction()
|
||||
}
|
||||
is TransactionState.AwaitingConfirmations -> {
|
||||
if (transactionState.confirmationCount < 1) {
|
||||
lottie_active_transaction.setAnimation(R.raw.lottie_send_success)
|
||||
lottie_active_transaction.playAnimation()
|
||||
title = "ZEC Sent"
|
||||
subtitle = "Awaiting Confirmations (${transactionState.confirmationCount}/10)"
|
||||
} else {
|
||||
// play confirmation counting animation
|
||||
}
|
||||
}
|
||||
}
|
||||
text_active_transaction_title.text = title
|
||||
|
@ -305,11 +346,14 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
private fun onActiveTransactionTransitionEnd() {
|
||||
// fixes a bug where the translation gets lost, during animation. As a nice side effect, visually, it makes the view appear to settle in to position
|
||||
header_active_transaction.translationZ = 10.0f
|
||||
button_active_transaction_cancel.apply {
|
||||
postDelayed({text = "cancel"}, 50L)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCancelActiveTransaction() {
|
||||
button_active_transaction_cancel.isEnabled = false
|
||||
button_active_transaction_cancel.text = "canceled"
|
||||
button_active_transaction_cancel.text = "cancel"
|
||||
header_active_transaction.animate().apply {
|
||||
translationZ(0f)
|
||||
duration = 200L
|
||||
|
@ -330,7 +374,6 @@ class HomeFragment : BaseFragment(), HomePresenter.HomeView {
|
|||
|
||||
} )
|
||||
}
|
||||
|
||||
homePresenter.onCancelActiveTransaction()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,26 +4,25 @@ import android.util.Log
|
|||
import cash.z.android.wallet.extention.Toaster
|
||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||
import cash.z.android.wallet.vo.WalletTransaction
|
||||
import cash.z.android.wallet.vo.WalletTransactionStatus
|
||||
import cash.z.android.wallet.vo.WalletTransactionStatus.RECEIVED
|
||||
import cash.z.android.wallet.vo.WalletTransactionStatus.SENT
|
||||
import cash.z.wallet.sdk.data.ActiveTransaction
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import cash.z.wallet.sdk.data.TransactionState
|
||||
import cash.z.wallet.sdk.vo.NoteQuery
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.channels.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.math.BigDecimal
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class HomePresenter(
|
||||
private val view: HomeView,
|
||||
private val synchronizer: Synchronizer
|
||||
) : Presenter {
|
||||
) : Presenter, CoroutineScope {
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job
|
||||
|
||||
interface HomeView : PresenterView {
|
||||
fun setTransactions(transactions: List<WalletTransaction>)
|
||||
|
@ -32,32 +31,20 @@ class HomePresenter(
|
|||
fun setActiveTransactions(activeTransactionMap: Map<ActiveTransaction, TransactionState>)
|
||||
}
|
||||
|
||||
private var balanceJob: Job? = null
|
||||
private var transactionJob: Job? = null
|
||||
private var progressJob: Job? = null
|
||||
private var activeTransactionJob: Job? = null
|
||||
|
||||
override suspend fun start() {
|
||||
Log.e("@TWIG-t", "homePresenter starting!")
|
||||
with(view) {
|
||||
balanceJob = launchBalanceBinder(synchronizer.repository.balance())
|
||||
transactionJob = launchTransactionBinder(synchronizer.repository.allTransactions())
|
||||
progressJob = launchProgressMonitor(synchronizer.downloader.progress())
|
||||
activeTransactionJob = launchActiveTransactionMonitor(synchronizer.activeTransactions())
|
||||
}
|
||||
launchBalanceBinder(synchronizer.repository.balance())
|
||||
launchTransactionBinder(synchronizer.repository.allTransactions())
|
||||
launchProgressMonitor(synchronizer.downloader.progress())
|
||||
launchActiveTransactionMonitor(synchronizer.activeTransactions())
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
Log.e("@TWIG-t", "homePresenter stopping!")
|
||||
|
||||
// using nullsafe 'also' to only set these to null when they weren't already null
|
||||
balanceJob?.cancel()?.also { balanceJob = null }
|
||||
transactionJob?.cancel()?.also { transactionJob = null }
|
||||
progressJob?.cancel()?.also { progressJob = null }
|
||||
activeTransactionJob?.cancel()?.also { progressJob = null }
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Long>) = launch {
|
||||
private fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Long>) = launch {
|
||||
var old: Long? = null
|
||||
Log.e("@TWIG-t", "balance binder starting!")
|
||||
for (new in channel) {
|
||||
|
@ -67,7 +54,7 @@ class HomePresenter(
|
|||
Log.e("@TWIG", "balance binder exiting!")
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchTransactionBinder(channel: ReceiveChannel<List<NoteQuery>>) = launch {
|
||||
private fun CoroutineScope.launchTransactionBinder(channel: ReceiveChannel<List<NoteQuery>>) = launch {
|
||||
Log.e("@TWIG", "transaction binder starting!")
|
||||
for (noteQueryList in channel) {
|
||||
Log.e("@TWIG", "received ${noteQueryList.size} transactions for presenting")
|
||||
|
@ -81,14 +68,15 @@ class HomePresenter(
|
|||
|
||||
private suspend fun updateTimeStamp(noteQuery: NoteQuery) = synchronizer.updateTimeStamp(noteQuery.height)
|
||||
|
||||
fun CoroutineScope.launchProgressMonitor(channel: ReceiveChannel<Int>) = launch {
|
||||
private fun CoroutineScope.launchProgressMonitor(channel: ReceiveChannel<Int>) = launch {
|
||||
Log.e("@TWIG", "progress monitor starting on thread ${Thread.currentThread().name}!")
|
||||
for (i in channel) {
|
||||
bind(i)
|
||||
}
|
||||
Log.e("@TWIG", "progress monitor exiting!")
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchActiveTransactionMonitor(channel: ReceiveChannel<Map<ActiveTransaction, TransactionState>>) = launch {
|
||||
private fun CoroutineScope.launchActiveTransactionMonitor(channel: ReceiveChannel<Map<ActiveTransaction, TransactionState>>) = launch {
|
||||
Log.e("@TWIG-v", "active transaction monitor starting!")
|
||||
for (i in channel) {
|
||||
bind(i)
|
||||
|
@ -96,20 +84,26 @@ class HomePresenter(
|
|||
Log.e("@TWIG-v", "active transaction monitor exiting!")
|
||||
}
|
||||
|
||||
private fun bind(old: Long?, new: Long) {
|
||||
|
||||
//
|
||||
// View Callbacks on Main Thread
|
||||
//
|
||||
|
||||
private fun bind(old: Long?, new: Long) = onMain {
|
||||
Log.e("@TWIG-t", "binding balance of $new")
|
||||
view.updateBalance(old ?: 0L, new)
|
||||
}
|
||||
|
||||
private fun bind(transactions: List<WalletTransaction>) {
|
||||
|
||||
private fun bind(transactions: List<WalletTransaction>) = onMain {
|
||||
Log.e("@TWIG-t", "binding ${transactions.size} walletTransactions")
|
||||
view.setTransactions(transactions)
|
||||
}
|
||||
|
||||
private fun bind(progress: Int) {
|
||||
private fun bind(progress: Int) = onMain {
|
||||
view.showProgress(progress)
|
||||
if(progress == 100) {
|
||||
view.launch {
|
||||
if (progress == 100) {
|
||||
launch {
|
||||
// TODO: remove this behavior and pull it down into the synchronizer
|
||||
Log.e("@TWIG-t", "triggering manual scan!")
|
||||
synchronizer.processor.scanBlocks()
|
||||
|
@ -117,24 +111,29 @@ class HomePresenter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun bind(activeTransactionMap: Map<ActiveTransaction, TransactionState>) {
|
||||
private fun bind(activeTransactionMap: Map<ActiveTransaction, TransactionState>) = onMain {
|
||||
Log.e("@TWIG-v", "binding a.t. map of size ${activeTransactionMap.size}")
|
||||
if (activeTransactionMap.isNotEmpty()) view.setActiveTransactions(activeTransactionMap)
|
||||
}
|
||||
|
||||
|
||||
fun onCancelActiveTransaction() {
|
||||
// TODO: hold a reference to the job and cancel it
|
||||
Toaster.short("Cancelled transaction!")
|
||||
}
|
||||
|
||||
private fun onMain(block: () -> Unit) = launch {
|
||||
withContext(Main) {
|
||||
Log.e("@TWIG-t", "running task on main thread - start ${coroutineContext[Job]} | ${coroutineContext[CoroutineName]}")
|
||||
block()
|
||||
Log.e("@TWIG-t", "running task on main thread - complete")
|
||||
}
|
||||
}
|
||||
|
||||
private fun NoteQuery.toWalletTransaction(timeOverride: Long? = null): WalletTransaction {
|
||||
// convert time from seconds to milliseconds
|
||||
val timestamp = if (timeOverride == null) time * 1000 else timeOverride * 1000
|
||||
Log.e("@TWIG-u", "setting timestamp to $timestamp for value $value")
|
||||
return WalletTransaction(height, if (sent) SENT else RECEIVED, timestamp, BigDecimal(value / 1e8))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cash.z.android.wallet.ui.util
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
|
||||
class ViewpagerHeader @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : MotionLayout(context, attrs, defStyleAttr), ViewPager.OnPageChangeListener {
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
val numPages = 3
|
||||
progress = (position + positionOffset) / (numPages - 1)
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 865 B |
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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/container_first_run"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:background="#81CAFF">
|
||||
|
||||
<cash.z.android.wallet.ui.util.ViewpagerHeader
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="230dp"
|
||||
app:layoutDescription="@xml/scene_15"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mountains"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/mountains" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/trees1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/trees"
|
||||
tools:layout_editor_absoluteX="23dp"
|
||||
tools:layout_editor_absoluteY="130dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/trees2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/trees"
|
||||
tools:layout_editor_absoluteX="7dp"
|
||||
tools:layout_editor_absoluteY="98dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/car"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/car"
|
||||
tools:layout_editor_absoluteX="7dp"
|
||||
tools:layout_editor_absoluteY="194dp" />
|
||||
|
||||
</cash.z.android.wallet.ui.util.ViewpagerHeader>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -37,4 +37,6 @@
|
|||
app:layout_anchor="@id/home_app_bar"
|
||||
app:layout_anchorGravity="bottom|center"
|
||||
app:srcCompat="@drawable/ic_zcashlogo_badge" />
|
||||
|
||||
<include layout="@layout/activity_main_first_run"/>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -9,6 +9,11 @@
|
|||
android:fillViewport="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/refresh_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/content_home"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -40,7 +45,7 @@
|
|||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_loop="false"
|
||||
app:lottie_rawRes="@raw/lottie_active_transaction_fail" />
|
||||
app:lottie_rawRes="@raw/lottie_send_common" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_active_transaction_title"
|
||||
|
@ -151,5 +156,5 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="image_empty_wallet,text_wallet_message" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<MotionScene
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:motion="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<Transition
|
||||
motion:constraintSetStart="@+id/start"
|
||||
motion:constraintSetEnd="@+id/end"
|
||||
motion:duration="1000"
|
||||
motion:interpolator="linear">
|
||||
|
||||
<OnSwipe
|
||||
motion:touchAnchorId="@+id/car"
|
||||
motion:touchAnchorSide="right"
|
||||
motion:dragDirection="dragRight" />
|
||||
|
||||
<ConstraintSet android:id="@+id/start">
|
||||
<Constraint
|
||||
android:id="@id/mountains"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:translationX="10dp"
|
||||
android:scaleX="1.2"
|
||||
android:scaleY="1.2"
|
||||
motion:layout_constraintTop_toTopOf="parent"/>
|
||||
<Constraint
|
||||
android:id="@id/trees1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="30dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
motion:layout_constraintLeft_toLeftOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"/>
|
||||
<Constraint
|
||||
android:id="@id/trees2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="90dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
motion:layout_constraintLeft_toLeftOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"/>
|
||||
<Constraint
|
||||
android:id="@id/car"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
motion:layout_constraintLeft_toLeftOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"/>
|
||||
</ConstraintSet>
|
||||
|
||||
<ConstraintSet android:id="@+id/end">
|
||||
<Constraint
|
||||
android:id="@id/mountains"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:translationX="-10dp"
|
||||
android:scaleX="1.2"
|
||||
android:scaleY="1.2"
|
||||
motion:layout_constraintTop_toTopOf="parent"/>
|
||||
<Constraint
|
||||
android:id="@id/trees1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="0dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
motion:layout_constraintLeft_toLeftOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"/>
|
||||
<Constraint
|
||||
android:id="@id/trees2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
motion:layout_constraintLeft_toLeftOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"/>
|
||||
<Constraint
|
||||
android:id="@id/car"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
motion:layout_constraintRight_toRightOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"/>
|
||||
</ConstraintSet>
|
||||
|
||||
</Transition>
|
||||
|
||||
</MotionScene>
|
Loading…
Reference in New Issue