Merge pull request #10 from gmale/feature/home-screen

home screen changes for preview release. Banners will wait until a future PR.
This commit is contained in:
Kevin Gorham 2018-12-12 17:41:29 -05:00 committed by GitHub
commit 689a9a522b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 1194 additions and 306 deletions

2
.gitignore vendored
View File

@ -3,7 +3,7 @@
*.ap_
# Built libraries
*.aar
#*.aar
# *.so
# Files for the ART/Dalvik VM

View File

@ -2,8 +2,33 @@
echo git tag -a \"v$(grep -oE 'versionName.*' zcash-android-wallet-app/app/build.gradle | sed 's/[^0-9]*\([0-9].*\w\).*/\1/')\" -m \""Released on $(date)"\"
echo
echo "Press ENTER to tag the release as above. Press CTRL+C to cancel."
read -p "TAG the release as above? Press y to tag ENTER to skip: [N] " -n 1 -r
read
if [[ $REPLY =~ ^[Yy]$ ]]
then
git tag -a v$(grep -oE 'versionName.*' zcash-android-wallet-app/app/build.gradle | sed 's/[^0-9]*\([0-9].*\w\).*/\1/') -m "Release on $(date)"
echo
echo "build tagged"
else
echo
echo "tag not created!"
fi
echo
read -p "PUSH TAG and TRIGGER BUILD to the wallet-team-members slack channel? [N] " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then
echo
git push origin --tags
echo "Tags pushed, build triggered. Opening bitrise to verify..."
xdg-open "https://app.bitrise.io/app/3f9040b242d98534#/builds"
else
echo
echo "tag not pushed!"
fi
echo
echo "Done!"
echo
git tag -a v$(grep -oE 'versionName.*' zcash-android-wallet-app/app/build.gradle | sed 's/[^0-9]*\([0-9].*\w\).*/\1/') -m "Release on $(date)"

View File

@ -13,8 +13,8 @@ android {
applicationId "cash.z.android.wallet"
minSdkVersion buildConfig.minSdkVersion
targetSdkVersion buildConfig.targetSdkVersion
versionCode 10 // todo: change this to 1_00_04 format, once we graduate beyond zero for the major version number because leading zeros indicate on octal number.
versionName "0.0.10-alpha"
versionCode 17 // todo: change this to 1_00_04 format, once we graduate beyond zero for the major version number because leading zeros indicate on octal number.
versionName "0.2.5-alpha"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}

View File

@ -8,15 +8,16 @@
<application
android:name=".ZcashWalletApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher_round"
android:roundIcon="@mipmap/ic_launcher_round"
android:icon="@mipmap/ic_launcher_shield"
android:roundIcon="@mipmap/ic_launcher_shield_round"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/ZcashTheme">
<activity
android:name=".ui.activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/ZcashTheme.NoActionBar">
android:theme="@style/ZcashTheme.NoActionBar"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,9 @@
package cash.z.android.wallet.extention
internal inline fun tryIgnore(block: () -> Unit) {
try { block() } catch(ignored: Throwable) {}
}
internal inline fun <T> tryNull(block: () -> T): T? {
return try { block() } catch(ignored: Throwable) { null }
}

View File

@ -0,0 +1,22 @@
package cash.z.android.wallet.extention
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.StringRes
import androidx.core.content.res.ResourcesCompat
import cash.z.android.wallet.ZcashWalletApplication
/**
* Grab a color out of the application resources, using the default theme
*/
@ColorInt
internal inline fun @receiver:ColorRes Int.toAppColor(): Int {
return ResourcesCompat.getColor(ZcashWalletApplication.instance.resources, this, ZcashWalletApplication.instance.theme)
}
/**
* Grab a string from the application resources
*/
internal inline fun @receiver:StringRes Int.toAppString(): String {
return ZcashWalletApplication.instance.getString(this)}

View File

@ -0,0 +1,15 @@
package cash.z.android.wallet.extention
import android.widget.Toast
import cash.z.android.wallet.ZcashWalletApplication
// For now, Toast is still a java class so we cannot write static extensions (per https://youtrack.jetbrains.com/issue/KT-11968)
// This is a quick workaround.
internal class Toaster {
companion object {
fun short(message: String) =
Toast.makeText(ZcashWalletApplication.instance, message, Toast.LENGTH_SHORT).show()
fun long(message: String) =
Toast.makeText(ZcashWalletApplication.instance, message, Toast.LENGTH_LONG).show()
}
}

View File

@ -1,37 +1,27 @@
package cash.z.android.wallet.ui.activity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.GravityCompat
import androidx.core.view.doOnLayout
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import cash.z.android.wallet.BuildConfig
import cash.z.android.wallet.R
import cash.z.android.wallet.di.module.SanityCheck
import cash.z.android.wallet.ui.fragment.HomeFragment
import com.google.android.material.snackbar.Snackbar
import dagger.Module
import dagger.android.ContributesAndroidInjector
import dagger.android.support.DaggerAppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.nav_header_main.*
import javax.inject.Inject
class MainActivity : DaggerAppCompatActivity() {
@Inject
lateinit var sanity: SanityCheck
// used to manage the drawer and drawerToggle interactions
lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var appBarConfiguration: AppBarConfiguration
lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
@ -56,7 +46,7 @@ class MainActivity : DaggerAppCompatActivity() {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
public fun setupNavigation() {
fun setupNavigation() {
// create and setup the navController and appbarConfiguration
navController = Navigation.findNavController(this, R.id.nav_host_fragment).also { n ->
appBarConfiguration = AppBarConfiguration(n.graph, drawer_layout).also { a ->
@ -68,21 +58,16 @@ class MainActivity : DaggerAppCompatActivity() {
// remove icon tint so that our colored nav icons show through
nav_view.itemIconTintList = null
// // counting the fab as navigation-related. So set it up here
// fab.setOnClickListener(::onFabClicked)
// navController.addOnNavigatedListener { _, destination ->
// if (destination.id == R.id.nav_home_fragment) fab.show() else fab.hide()
// }
nav_view.doOnLayout {
text_nav_header_subtitle.text = "Version ${BuildConfig.VERSION_NAME}"
}
}
private fun onFabClicked(view: View) {
Snackbar.make(view, if (sanity.stillSane) "Your imaginary ZEC is in flight." else "You've lost your marbles.", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
companion object {
init {
// Enable vector drawable magic
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}
}
}

View File

@ -0,0 +1,60 @@
package cash.z.android.wallet.ui.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import cash.z.android.wallet.R
import cash.z.android.wallet.extention.toAppColor
import cash.z.android.wallet.vo.WalletTransaction
import java.math.BigDecimal
import java.math.MathContext
import java.math.RoundingMode
import java.text.SimpleDateFormat
import java.util.*
class TransactionAdapter(private val transactions: MutableList<WalletTransaction>) :
RecyclerView.Adapter<TransactionViewHolder>() {
init {
transactions.sortBy { it.timestamp * -1 }
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_transaction, parent, false)
return TransactionViewHolder(itemView)
}
override fun getItemCount(): Int = transactions.size
override fun onBindViewHolder(holder: TransactionViewHolder, position: Int) = holder.bind(transactions[position])
fun setTransactions(txs: List<WalletTransaction>) {
transactions.clear()
transactions.addAll(txs)
notifyDataSetChanged()
}
}
class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val status = itemView.findViewById<View>(R.id.view_transaction_status)
private val timestamp = itemView.findViewById<TextView>(R.id.text_transaction_timestamp)
private val amount = itemView.findViewById<TextView>(R.id.text_transaction_amount)
private val background = itemView.findViewById<View>(R.id.container_transaction)
private val formatter = SimpleDateFormat("M/d h:mma", Locale.getDefault())
fun bind(tx: WalletTransaction) {
val sign = if(tx.amount > BigDecimal.ZERO) "+" else "-"
val rowColor = if(adapterPosition.rem(2) == 0) R.color.zcashBlueGray else R.color.zcashWhite
val amountColor = if(tx.amount > BigDecimal.ZERO) R.color.colorPrimary else R.color.text_dark_dimmed
background.setBackgroundColor(rowColor.toAppColor())
status.setBackgroundColor(tx.status.color.toAppColor())
timestamp.text = formatter.format(tx.timestamp)
amount.text = String.format("$sign %,.3f", tx.amount.round(MathContext(3, RoundingMode.HALF_EVEN )).abs())
amount.setTextColor(amountColor.toAppColor())
}
}

View File

@ -0,0 +1,4 @@
package cash.z.android.wallet.ui.fragment
class AboutFragment : PlaceholderFragment()

View File

@ -0,0 +1,4 @@
package cash.z.android.wallet.ui.fragment
class HistoryFragment : PlaceholderFragment()

View File

@ -2,6 +2,9 @@ package cash.z.android.wallet.ui.fragment
import android.app.Activity
import android.os.Bundle
import android.text.SpannableString
import android.text.Spanned
import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -9,25 +12,31 @@ import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.doOnLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import cash.z.android.wallet.R
import cash.z.android.wallet.di.module.SanityCheck
import cash.z.android.wallet.extention.toAppColor
import cash.z.android.wallet.extention.toAppString
import cash.z.android.wallet.extention.tryIgnore
import cash.z.android.wallet.ui.activity.MainActivity
import cash.z.wallet.sdk.jni.JniConverter
import cash.z.android.wallet.ui.adapter.TransactionAdapter
import cash.z.android.wallet.ui.util.TopAlignedSpan
import cash.z.android.wallet.vo.WalletTransaction
import cash.z.android.wallet.vo.WalletTransactionStatus
import com.leinardi.android.speeddial.SpeedDialActionItem
import dagger.Module
import dagger.android.ContributesAndroidInjector
import kotlinx.android.synthetic.main.fragment_home.*
import javax.inject.Inject
import kotlinx.android.synthetic.main.include_home_content.*
import kotlinx.android.synthetic.main.include_home_header.*
import java.math.BigDecimal
import kotlin.random.Random
/**
* Fragment representing the home screen of the app. This is the screen most often seen by the user when launching the
* application.
*/
class HomeFragment : BaseFragment() {
// TODO: remove this test object. it is currently just used to exercise the rust code
var converter: JniConverter = JniConverter()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@ -40,20 +49,30 @@ class HomeFragment : BaseFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).let { mainActivity ->
mainActivity.setSupportActionBar(toolbar)
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)
// TODO remove this test code
val seed = byteArrayOf(0x77, 0x78, 0x79)
val result = converter.getAddress("dummyseed".toByteArray())
text_wallet_message.text = "Your address:\n$result"
// TODO: remove this test behavior
image_logo.setOnClickListener {
toggle(!empty)
}
}
override fun onResume() {
super.onResume()
view!!.postDelayed( {toggle(false)}, delay * 2L)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initFab(activity!!)
recycler_transactions.layoutManager = LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
recycler_transactions.adapter = TransactionAdapter(createDummyTransactions(60))
}
/**
@ -66,7 +85,7 @@ class HomeFragment : BaseFragment() {
val nav = (activity as MainActivity).navController
HomeFab.values().forEach {
speedDial.addActionItem(it.createItem(activity))
speedDial.addActionItem(it.createItem())
}
speedDial.setOnActionSelectedListener { item ->
@ -75,6 +94,33 @@ class HomeFragment : BaseFragment() {
}
}
private val createItem: HomeFab.() -> SpeedDialActionItem = {
SpeedDialActionItem.Builder(id, icon)
.setFabBackgroundColor(bgColor.toAppColor())
.setFabImageTintColor(R.color.zcashWhite.toAppColor())
.setLabel(label.toAppString())
.setLabelClickable(true)
.create()
}
fun setUsdValue(value: Double) {
val valueString = String.format("$%,.2f",value)
val hairSpace = "\u200A"
// val adjustedValue = "$$hairSpace$valueString"
val textSpan = SpannableString(valueString)
textSpan.setSpan(TopAlignedSpan(), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
textSpan.setSpan(TopAlignedSpan(), valueString.length - 3, valueString.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
text_balance_usd.text = textSpan
}
fun setZecValue(value: Double) {
text_balance_zec.text = if(value == 0.0) "0" else String.format("%.3f",value)
// // bugfix: there is a bug in motionlayout that causes text to flicker as it is resized because the last character doesn't fit. Padding both sides with a thin space works around this bug.
// val hairSpace = "\u200A"
// val adjustedValue = "$hairSpace$valueString$hairSpace"
// text_balance_zec.text = adjustedValue
}
/**
* Defines the basic properties of each FAB button for use while initializing the FAB
*/
@ -108,23 +154,120 @@ class HomeFragment : BaseFragment() {
R.id.nav_send_fragment
);
fun createItem(activity: Activity): SpeedDialActionItem =
SpeedDialActionItem.Builder(id, icon)
.setFabBackgroundColor(ResourcesCompat.getColor(activity.resources, bgColor, activity.theme))
.setFabImageTintColor(ResourcesCompat.getColor(activity.resources, R.color.zcashWhite, activity.theme))
.setLabel(activity.getString(label))
.setLabelClickable(true)
.create()
companion object {
fun fromId(id: Int): HomeFab? = values().firstOrNull { it.id == id }
}
}
// ---------------------------------------------------------------------------------------------------------------------
// TODO: Delete these test functions
// ---------------------------------------------------------------------------------------------------------------------
var empty = false
val delay = 20L
lateinit var headerEmptyViews: Array<View>
lateinit var headerFullViews: Array<View>
fun shrink(): Double {
return text_balance_zec.text.toString().trim().toDouble() - Random.nextDouble(5.0)
}
fun grow(): Double {
return text_balance_zec.text.toString().trim().toDouble() + Random.nextDouble(5.0)
}
fun reduceValue() {
shrink().let {
if(it < 0) { setZecValue(0.0); toggleViews(empty); forceRedraw() }
else view?.postDelayed({
setZecValue(it)
setUsdValue(it*75.0)
reduceValue()
}, delay)
}
}
fun increaseValue(target: Double) {
grow().let {
if(it > target) { setZecValue(target); setUsdValue(target*75.0); toggleViews(empty) }
else view?.postDelayed({
setZecValue(it)
setUsdValue(it*75.0)
increaseValue(target)
if (headerFullViews[0].parent == null || headerEmptyViews[0].parent != null) toggleViews(false)
forceRedraw()
}, delay)
}
}
fun forceRedraw() {
view?.postDelayed({
container_home_header.progress = container_home_header.progress - 0.1f
}, delay * 2)
}
internal fun toggle(isEmpty: Boolean) {
toggleValues(isEmpty)
}
internal fun toggleViews(isEmpty: Boolean) {
if(isEmpty) {
view?.postDelayed({
group_empty_view_items.visibility = View.VISIBLE
group_full_view_items.visibility = View.GONE
headerFullViews.forEach { container_home_header.removeView(it) }
headerEmptyViews.forEach {
tryIgnore {
container_home_header.addView(it)
}
}
}, delay)
} else {
view?.postDelayed({
group_empty_view_items.visibility = View.GONE
group_full_view_items.visibility = View.VISIBLE
headerEmptyViews.forEach { container_home_header.removeView(it) }
headerFullViews.forEach {
tryIgnore {
container_home_header.addView(it)
}
}
}, delay)
}
}
internal fun toggleValues(isEmpty: Boolean) {
empty = isEmpty
if(empty) {
reduceValue()
} else {
increaseValue(Random.nextDouble(20.0, 100.0))
}
}
}
@Module
abstract class HomeFragmentModule {
@ContributesAndroidInjector
abstract fun contributeHomeFragment(): HomeFragment
}
}
//TODO: delete this test code
internal fun createDummyTransactions(size: Int): MutableList<WalletTransaction> {
val transactions = mutableListOf<WalletTransaction>()
repeat(size) {
transactions.add(createDummyTransaction())
}
return transactions
}
internal fun createDummyTransaction(): WalletTransaction {
val now = System.currentTimeMillis()
val before = now - (4 * DateUtils.WEEK_IN_MILLIS)
val amount = BigDecimal(Random.nextDouble(0.1, 15.0) * arrayOf(-1, 1).random())
val status = if(amount > BigDecimal.ZERO) WalletTransactionStatus.SENT else WalletTransactionStatus.RECEIVED
return WalletTransaction(
status,
Random.nextLong(before, now),
amount
)
}

View File

@ -0,0 +1,4 @@
package cash.z.android.wallet.ui.fragment
class ImportFragment : PlaceholderFragment()

View File

@ -0,0 +1,37 @@
package cash.z.android.wallet.ui.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import cash.z.android.wallet.R
import cash.z.android.wallet.ui.activity.MainActivity
/**
* Fragment for sending Zcash.
*
*/
open class PlaceholderFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_placeholder, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).let { mainActivity ->
mainActivity.setSupportActionBar(view.findViewById(R.id.toolbar))
mainActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
mainActivity.supportActionBar?.setTitle(R.string.destination_title_placeholder)
}
}
}

View File

@ -14,7 +14,6 @@ import cash.z.android.wallet.ui.util.AddressPartNumberSpan
import cash.z.wallet.sdk.jni.JniConverter
import dagger.Module
import dagger.android.ContributesAndroidInjector
import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.fragment_receive.*
import javax.inject.Inject
@ -42,7 +41,7 @@ class ReceiveFragment : BaseFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).let { mainActivity ->
mainActivity.setSupportActionBar(toolbar)
mainActivity.setSupportActionBar(view.findViewById(R.id.toolbar))
mainActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
mainActivity.supportActionBar?.setTitle(R.string.destination_title_receive)
}
@ -56,8 +55,7 @@ class ReceiveFragment : BaseFragment() {
text_address_part_8
)
}
override fun onResume() {
super.onResume()
@ -66,7 +64,11 @@ class ReceiveFragment : BaseFragment() {
}
private fun onAddressLoaded(address: String) {
qrecycler.load(address).into(receive_qr_code)
qrecycler.load(address)
.withQuietZoneSize(3)
.withCorrectionLevel(QRecycler.CorrectionLevel.MEDIUM)
.into(receive_qr_code)
address.chunked(address.length/8).forEachIndexed { i, part ->
setAddressPart(i, part)
}

View File

@ -3,13 +3,12 @@ package cash.z.android.wallet.ui.fragment
import android.content.Context
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import cash.z.android.wallet.R
import cash.z.android.wallet.ui.activity.MainActivity
import kotlinx.android.synthetic.main.fragment_home.*
// TODO: Rename parameter arguments, choose names that match
@ -50,7 +49,7 @@ class RequestFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).setSupportActionBar(toolbar)
(activity as MainActivity).setSupportActionBar(view.findViewById(R.id.toolbar))
(activity as MainActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true)
}

View File

@ -1,44 +1,19 @@
package cash.z.android.wallet.ui.fragment
import android.content.Context
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import cash.z.android.wallet.R
import cash.z.android.wallet.ui.activity.MainActivity
import kotlinx.android.synthetic.main.fragment_home.*
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Activities that contain this fragment must implement the
* [SendFragment.OnFragmentInteractionListener] interface
* to handle interaction events.
* Use the [SendFragment.newInstance] factory method to
* create an instance of this fragment.
* Fragment for sending Zcash.
*
*/
class SendFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var listener: OnFragmentInteractionListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@ -48,56 +23,15 @@ class SendFragment : Fragment() {
return inflater.inflate(R.layout.fragment_send, container, false)
}
// TODO: Rename method, update argument and hook method into UI event
fun onButtonPressed(uri: Uri) {
listener?.onFragmentInteraction(uri)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).setSupportActionBar(toolbar)
(activity as MainActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true)
(activity as MainActivity).let { mainActivity ->
mainActivity.setSupportActionBar(view.findViewById(R.id.toolbar))
mainActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
mainActivity.supportActionBar?.setTitle(R.string.destination_title_send)
}
}
override fun onDetach() {
super.onDetach()
listener = null
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
*
*
* See the Android Training lesson [Communicating with Other Fragments]
* (http://developer.android.com/training/basics/fragments/communicating.html)
* for more information.
*/
interface OnFragmentInteractionListener {
// TODO: Update argument type and name
fun onFragmentInteraction(uri: Uri)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SendFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
SendFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}

View File

@ -0,0 +1,4 @@
package cash.z.android.wallet.ui.fragment
class SettingsFragment : PlaceholderFragment()

View File

@ -28,13 +28,13 @@ class AddressPartNumberSpan(
override fun describeContents() = 0
override fun updateMeasureState(textPaint: TextPaint) {
textPaint.textSize = textPaint.textSize * proportion // from RelativeSizeSpan
textPaint.baselineShift += (textPaint.ascent() / 2).toInt() // from SuperscriptSpan
textPaint.textSize = textPaint.textSize * proportion // from RelativeSizeSpan
}
override fun updateDrawState(textPaint: TextPaint) {
textPaint.baselineShift += (textPaint.ascent() / 2).toInt() // from SuperscriptSpan (baseline must shift before resizing or else it will not properly align to the top of the text)
textPaint.textSize = textPaint.textSize * proportion // from RelativeSizeSpan
textPaint.baselineShift += (textPaint.ascent() / 2).toInt() // from SuperscriptSpan
textPaint.color = color // from ForegroundColorSpan
}
}

View File

@ -0,0 +1,27 @@
package cash.z.android.wallet.ui.util
import android.text.TextPaint
import android.text.style.RelativeSizeSpan
/**
* A span used for numbering the parts of an address. It combines a [android.text.style.RelativeSizeSpan],
* [android.text.style.SuperscriptSpan], and a [android.text.style.ForegroundColorSpan] into one class for efficiency.
*/
class TopAlignedSpan(
val proportion: Float = 0.625f
) : RelativeSizeSpan(proportion) {
override fun updateMeasureState(textPaint: TextPaint) {
updateDrawState(textPaint)
}
override fun updateDrawState(textPaint: TextPaint) {
val initialSize = textPaint.textSize
val scaledSize = textPaint.textSize * proportion
val sizeDelta = scaledSize - initialSize + (textPaint.ascent()/2)
textPaint.textSize = scaledSize
// shift baseline up by change in textSize and adjust for density since size is in pixels
textPaint.baselineShift += (sizeDelta/textPaint.density).toInt()
}
}

View File

@ -0,0 +1,23 @@
package cash.z.android.wallet.ui.view
import android.content.Context
import android.util.AttributeSet
import androidx.constraintlayout.motion.widget.MotionLayout
import com.google.android.material.appbar.AppBarLayout
class CollapsingMotionToolbar @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : MotionLayout(context, attrs, defStyleAttr), AppBarLayout.OnOffsetChangedListener {
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
progress = -verticalOffset / appBarLayout.totalScrollRange.toFloat()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
(parent as? AppBarLayout)?.let { appBarLayout ->
// appBarLayout.removeOnOffsetChangedListener(this)
appBarLayout.addOnOffsetChangedListener(this)
}
}
}

View File

@ -0,0 +1,12 @@
package cash.z.android.wallet.vo
import cash.z.android.wallet.R
import androidx.annotation.ColorRes
import java.math.BigDecimal
data class WalletTransaction(val status: WalletTransactionStatus, val timestamp: Long, val amount: BigDecimal)
enum class WalletTransactionStatus(@ColorRes val color: Int) {
SENT(R.color.colorPrimary),
RECEIVED(R.color.colorAccent);
}

View File

@ -0,0 +1,69 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="50dp"
android:height="50dp"
android:viewportWidth="50"
android:viewportHeight="50">
<path
android:pathData="M25,0L25,0A25,25 0,0 1,50 25L50,25A25,25 0,0 1,25 50L25,50A25,25 0,0 1,0 25L0,25A25,25 0,0 1,25 0z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M25,25m-22.75,0a22.75,22.75 0,1 1,45.5 0a22.75,22.75 0,1 1,-45.5 0"
android:strokeLineJoin="round"
android:strokeWidth="0.5"
android:fillColor="#FFFFFF"
android:fillType="evenOdd">
<aapt:attr name="android:strokeColor">
<gradient
android:startY="2.25"
android:startX="25"
android:endY="47.304756"
android:endX="25"
android:type="linear">
<item android:offset="0" android:color="#00000000"/>
<item android:offset="0.8" android:color="#05000000"/>
<item android:offset="1" android:color="#0A000000"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M25,25m-22.75,0a22.75,22.75 0,1 1,45.5 0a22.75,22.75 0,1 1,-45.5 0"
android:strokeLineJoin="round"
android:strokeWidth="0.5"
android:fillColor="#00000000"
android:fillType="evenOdd">
<aapt:attr name="android:strokeColor">
<gradient
android:startY="2.25"
android:startX="25"
android:endY="47.75"
android:endX="25"
android:type="linear">
<item android:offset="0" android:color="#1EFFFFFF"/>
<item android:offset="0.2" android:color="#0FFFFFFF"/>
<item android:offset="1" android:color="#00FFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M25.0005,2C12.3176,2 2,12.3176 2,24.9995C2,37.6814 12.3176,48 25.0005,48C37.6834,48 48,37.6824 48,24.9995C48,12.3166 37.6824,2 25.0005,2ZM25.0005,44.203C14.4115,44.203 5.797,35.5885 5.797,24.9995C5.797,14.4105 14.4115,5.797 25.0005,5.797C35.5895,5.797 44.203,14.4115 44.203,24.9995C44.203,35.5875 35.5885,44.203 25.0005,44.203Z"
android:strokeWidth="1"
android:fillColor="#231F20"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M24.9747,24.9747m-18.0462,0a18.0462,18.0462 0,1 1,36.0923 0a18.0462,18.0462 0,1 1,-36.0923 0"
android:strokeWidth="1"
android:fillColor="#F4B728"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M33.0626,17.5611l0,-3.5028l-6.2269,0l0,-3.8441l-3.8242,0l0,3.8441l-6.2259,0l0,4.6398l9.6521,0l-7.8934,10.9311l-1.7587,2.2496l0,3.5028l6.2259,0l0,3.8318l0.4587,0l0,0.0163l2.9069,0l0,-0.0163l0.4587,0l0,-3.8318l6.2269,0l0,-4.6398l-9.6532,0l7.8934,-10.9311z"
android:strokeWidth="1"
android:fillColor="#231F20"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>

View File

@ -1,34 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0"/>
<item
android:color="#00000000"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1"/>
</vector>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View File

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="358dp"
android:height="418dp"
android:viewportWidth="358"
android:viewportHeight="418">
<path
android:pathData="M179,0C207.069,11.901 236.599,23.2 267.591,33.897C298.582,44.595 328.719,53.128 358,59.497C354.385,162.895 337.225,240.396 306.519,292C275.814,343.603 233.307,385.603 179,418C124.693,385.603 82.186,343.603 51.481,292C20.775,240.396 3.615,162.895 0,59.497C29.281,53.128 59.418,44.595 90.409,33.897C121.401,23.2 150.931,11.901 179,0Z"
android:strokeAlpha="0.2"
android:strokeWidth="1"
android:fillColor="#000000"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillAlpha="0.2"/>
</vector>

View File

@ -0,0 +1,6 @@
<vector android:height="46dp" android:viewportHeight="490.18"
android:viewportWidth="493.33" android:width="46dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#231f20" android:pathData="M245.4,20C121.11,20 20,121.11 20,245.39s101.11,225.4 225.4,225.4 225.39,-101.11 225.39,-225.4S369.68,20 245.4,20ZM245.4,433.58c-103.77,0 -188.19,-84.42 -188.19,-188.19S141.63,57.21 245.4,57.21s188.18,84.42 188.18,188.18S349.16,433.58 245.4,433.58Z"/>
<path android:fillColor="#f4b728" android:pathData="M245.4,245.39m-177.65,0a177.65,177.65 0,1 1,355.3 0a177.65,177.65 0,1 1,-355.3 0"/>
<path android:fillColor="#231f20" android:pathData="M325.78,175.13l0,-34.38l-61.5,0l0,-37.73l-37.77,0l0,37.73l-61.49,0l0,45.54l95.33,0l-77.96,107.29l-17.37,22.08l0,34.38l61.49,0l0,37.61l4.53,0l0,0.16l28.71,0l0,-0.16l4.53,0l0,-37.61l61.5,0l0,-45.54l-95.34,0l77.96,-107.29l17.38,-22.08z"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="11dp"
android:height="19dp"
android:viewportWidth="11"
android:viewportHeight="19">
<path
android:pathData="M10.1895,4.8011l0,-2.2884l-3.8975,0l0,-2.5127l-2.3939,0l0,2.5127l-3.8981,0l0,3.0313l6.0424,0l-4.941,7.144l-1.1014,1.4698l0,2.289l3.8981,0l0,2.5044l0.2868,0l0,0.0103l1.8197,0l0,-0.0103l0.2874,0l0,-2.5044l3.8975,0l0,-3.0313l-6.0424,0l4.941,-7.1447z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -1,61 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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/layout_home_fragment"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.HomeFragment">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/home_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/home_app_bar_expanded_height"
android:theme="@style/ZcashTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="180dp"
app:popupTheme="@style/ZcashTheme.PopupOverlay" />
<include layout="@layout/include_home_header" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_empty_wallet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_emptywallet"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.6" />
<TextView
android:id="@+id/text_wallet_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="#AAAAAA"
android:padding="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_empty_wallet"
tools:text="Your wallet is empty." />
</androidx.constraintlayout.widget.ConstraintLayout>
<include layout="@layout/include_home_content" />
<!-- FAB -->
<com.leinardi.android.speeddial.SpeedDialView
android:id="@+id/sd_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:sdMainFabClosedSrc="@drawable/ic_add_white_24dp"
app:sdMainFabClosedBackgroundColor="@color/fab_closed_color"
app:sdMainFabOpenedBackgroundColor="@color/fab_open_color"/>
app:sdMainFabClosedSrc="@drawable/ic_add_white_24dp"
app:sdMainFabOpenedBackgroundColor="@color/fab_open_color" />
<!-- Zcash badge -->
<ImageView
android:id="@+id/image_logo"
android:layout_width="50dp"
android:layout_height="50dp"
android:elevation="6dp"
app:layout_anchor="@id/home_app_bar"
app:layout_anchorGravity="bottom|center"
app:srcCompat="@drawable/ic_zcashlogo_badge" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<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/layout_placeholder_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.PlaceholderFragment">
<include layout="@layout/include_app_bar"
tools:ignore="MissingConstraints" />
<TextView
android:id="@+id/text_placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/destination_title_placeholder"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -22,14 +22,14 @@
<ImageView
android:id="@+id/image_shield"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:src="@drawable/shield"
android:layout_height="0dp"
android:scaleType="fitXY"
app:srcCompat="@drawable/ic_shield"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.491"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/include_toolbar"
app:layout_constraintDimensionRatio="H,1:1.1676"
app:layout_constraintVertical_bias="0.062"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.84988" />
@ -45,9 +45,9 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/image_shield"
app:layout_constraintVertical_bias="0.318"
app:layout_constraintVertical_bias="0.272"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.58111" />
app:layout_constraintWidth_percent="0.59" />
<ImageView
android:layout_width="0dp"

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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/scrollable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<!-- Label: Past Activity -->
<TextView
android:id="@+id/text_transaction_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Past Activity"
android:textColor="@color/text_dark"
android:textSize="@dimen/text_size_body_2"
android:textStyle="bold"
android:paddingBottom="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Transactions -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_transactions"
android:layout_width="0dp"
android:layout_height="0dp"
android:clipToPadding="false"
android:paddingBottom="72dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_transaction_header"
tools:itemCount="15"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_transaction"
tools:orientation="vertical" />
<!-- Empty: image -->
<ImageView
android:id="@+id/image_empty_wallet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.281966"
app:srcCompat="@drawable/ic_emptywallet" />
<!-- Empty: message -->
<TextView
android:id="@+id/text_wallet_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:padding="16dp"
android:text="@string/home_empty_wallet"
android:textColor="#AAAAAA"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_empty_wallet" />
<!-- -->
<!-- Groups -->
<!-- -->
<androidx.constraintlayout.widget.Group
android:id="@+id/group_full_view_items"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="text_transaction_header,recycler_transactions" />
<androidx.constraintlayout.widget.Group
android:id="@+id/group_empty_view_items"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="image_empty_wallet,text_wallet_message" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -0,0 +1,128 @@
<?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.
-->
<cash.z.android.wallet.ui.view.CollapsingMotionToolbar 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_home_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
android:minHeight="?attr/actionBarSize"
app:layoutDescription="@xml/scene_fragment_home_header"
app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"
tools:showIn="@layout/fragment_home">
<Space
android:id="@+id/space_left_icon"
android:layout_width="50dp"
android:layout_height="?attr/actionBarSize"/>
<!-- Toolbar -->
<androidx.appcompat.widget.Toolbar
android:id="@+id/home_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:popupTheme="@style/ZcashTheme.PopupOverlay" />
<!-- balance -->
<TextView
android:id="@+id/text_balance_zec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="4dp"
android:shadowColor="@color/text_shadow"
android:shadowDx="0"
android:shadowDy="8"
android:shadowRadius="24"
android:text="35.021"
android:textColor="@color/zcashWhite"
android:textSize="60dp" />
<!-- balance: empty -->
<TextView
android:id="@+id/text_balance_zec_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="4dp"
android:shadowColor="@color/text_shadow"
android:shadowDx="0"
android:shadowDy="8"
android:shadowRadius="24"
android:text="0"
android:textColor="@color/zcashWhite"
android:textSize="60dp" />
<!-- Zec symbol: shadow -->
<ImageView
android:id="@+id/image_zec_symbol_balance_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#B3000000"
app:srcCompat="@drawable/ic_zec_symbol" />
<!-- Zec symbol -->
<ImageView
android:id="@+id/image_zec_symbol_balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_zec_symbol" />
<!-- Zec symbol empty: shadow -->
<ImageView
android:id="@+id/image_zec_symbol_balance_shadow_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#B3000000"
app:srcCompat="@drawable/ic_zec_symbol" />
<!-- Zec symbol empty -->
<ImageView
android:id="@+id/image_zec_symbol_balance_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_zec_symbol" />
<!-- Balance includes active transactions -->
<TextView
android:id="@+id/text_balance_includes_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Balance includes active transactions"
android:textColor="@color/text_light_dimmed"
android:textSize="@dimen/text_size_caption" />
<TextView
android:id="@+id/text_balance_usd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:text="$5,459.32"
android:textColor="@color/text_light_dimmed"
android:textSize="24dp" />
<TextView
android:id="@+id/text_balance_zec_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_zec_symbol"
android:drawableLeft="@drawable/ic_zec_symbol"
android:drawablePadding="6dp"
android:text="is a currency symbol for ZEC"
android:textColor="@color/zcashWhite"
android:textSize="16dp"
/>
</cash.z.android.wallet.ui.view.CollapsingMotionToolbar>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<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_transaction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/home_transaction_item_background"
android:paddingEnd="8dp"
android:paddingRight="8dp"
android:elevation="1dp"
tools:ignore="RtlSymmetry">
<View
android:id="@+id/view_transaction_status"
android:layout_width="6dp"
android:layout_height="0dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:background="@color/colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/text_transaction_timestamp"
app:layout_constraintBottom_toBottomOf="@id/text_transaction_timestamp"/>
<TextView
android:id="@+id/text_transaction_timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:text="8/23 3:24pm"
android:textSize="@dimen/text_size_body_2"
android:textColor="@color/text_dark_dimmed"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/view_transaction_status"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_transaction_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+ 4.244"
android:textColor="@color/colorPrimary"
android:textSize="@dimen/text_size_body_2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<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/linearLayout"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
@ -14,21 +13,13 @@
android:paddingBottom="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_status_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintGuide_begin="24dp"
android:orientation="horizontal" />
<ImageView
android:id="@+id/image_nav_header_logo"
android:layout_width="92dp"
android:layout_height="92dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/nav_header_desc"
android:layout_marginBottom="16dp"
app:srcCompat="@drawable/zcash_logo_with_shadow"
app:layout_constraintTop_toBottomOf="@id/guideline_status_bar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/text_nav_header_title"

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/launcher_icon_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground_shield"/>
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/launcher_icon_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground_shield"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -35,5 +35,27 @@
android:name="cash.z.android.wallet.ui.fragment.RequestFragment"
android:label="@string/destination_title_request"
tools:layout="@layout/fragment_request" />
<!-- unimplemented -->
<fragment
android:id="@+id/nav_history_fragment"
android:name="cash.z.android.wallet.ui.fragment.HistoryFragment"
android:label="@string/destination_title_history"
tools:layout="@layout/fragment_placeholder" />
<fragment
android:id="@+id/nav_about_fragment"
android:name="cash.z.android.wallet.ui.fragment.AboutFragment"
android:label="@string/destination_title_about"
tools:layout="@layout/fragment_placeholder" />
<fragment
android:id="@+id/nav_import_fragment"
android:name="cash.z.android.wallet.ui.fragment.ImportFragment"
android:label="@string/destination_title_import"
tools:layout="@layout/fragment_placeholder" />
<fragment
android:id="@+id/nav_settings_fragment"
android:name="cash.z.android.wallet.ui.fragment.SettingsFragment"
android:label="@string/destination_title_settings"
tools:layout="@layout/fragment_placeholder" />
</navigation>

View File

@ -20,11 +20,15 @@
<!-- This palette should be kept as small as possible and should map directly to the design style guide -->
<color name="zcashBlue">#2196F3</color>
<color name="zcashBlueGray">#0D364C66</color>
<color name="zcashWhite">#FFFFFF</color>
<color name="zcashWhite_87">#BFFFFFFF</color>
<color name="zcashBlack_light">#2B2B2B</color>
<color name="zcashBlack_12">#1F000000</color>
<color name="zcashBlack_40">#66000000</color>
<color name="zcashBlack_54">#8A000000</color>
<color name="zcashBlack_87">#DD000000</color>
<color name="zcashPrimaryMedium">#136E6E</color>
<!-- -->
<!-- named colors -->
@ -42,11 +46,17 @@
<!-- text -->
<color name="text_light">@color/zcashWhite</color>
<color name="text_light_dimmed">@color/zcashWhite_87</color>
<color name="text_dark">@color/zcashBlack_87</color>
<color name="text_dark_dimmed">@color/zcashBlack_54</color>
<color name="text_shadow">@color/zcashBlack_40</color>
<!-- backgrounds -->
<color name="fragment_receive_background">@color/zcashBlack_light</color>
<color name="fragment_request_background">@color/colorPrimary</color>
<color name="launcher_icon_background">@color/zcashPrimaryMedium</color>
<color name="receive_title_background">@color/zcashBlack_12</color>
<color name="home_transaction_item_background">@color/zcashBlueGray</color>
</resources>

View File

@ -3,8 +3,8 @@
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<dimen name="nav_header_height">176dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="nav_header_height">206dp</dimen>
<dimen name="home_app_bar_expanded_height">180dp</dimen>
<!-- Text Sizes -->

View File

@ -12,6 +12,11 @@
<string name="destination_title_send">Send Zcash</string>
<string name="destination_title_receive">Receive Zcash</string>
<string name="destination_title_request">Request Zcash</string>
<string name="destination_title_history">History</string>
<string name="destination_title_about">About</string>
<string name="destination_title_import">Import</string>
<string name="destination_title_settings">Settings</string>
<string name="destination_title_placeholder">Coming Soon</string>
<string name="destination_menu_label_home">Home</string>
<string name="destination_menu_label_send">Send</string>
<string name="destination_menu_label_receive">Receive</string>
@ -23,5 +28,7 @@
<!-- Screen copy -->
<string name="receive_address_title">Your Zcash shielded address</string>
<string name="home_empty_wallet">Your wallet is empty.</string>
<string name="home_empty_wallet_collapse">Future transactions will show up here.</string>
</resources>

View File

@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@+id/start">
<ConstraintSet android:id="@id/start">
<Constraint
android:id="@id/space_left_icon"
android:layout_width="72dp"
android:layout_height="?attr/actionBarSize"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/home_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/text_balance_zec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent"
motion:layout_constraintVertical_bias="0.36">
<CustomAttribute
motion:attributeName="textSize"
motion:customFloatValue="60.0" />
</Constraint>
<Constraint
android:id="@id/text_balance_zec_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent"
motion:layout_constraintVertical_bias="0.36"/>
<Constraint
android:id="@id/image_zec_symbol_balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
motion:layout_constraintEnd_toStartOf="@id/text_balance_zec"
motion:layout_constraintTop_toTopOf="@id/text_balance_zec" />
<Constraint
android:id="@id/image_zec_symbol_balance_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
motion:layout_constraintStart_toStartOf="@id/image_zec_symbol_balance"
motion:layout_constraintTop_toTopOf="@+id/image_zec_symbol_balance" />
<Constraint
android:id="@id/image_zec_symbol_balance_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
motion:layout_constraintEnd_toStartOf="@id/text_balance_zec_empty"
motion:layout_constraintTop_toTopOf="@id/text_balance_zec_empty" />
<Constraint
android:id="@id/image_zec_symbol_balance_shadow_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
motion:layout_constraintStart_toStartOf="@id/image_zec_symbol_balance_empty"
motion:layout_constraintTop_toTopOf="@+id/image_zec_symbol_balance_empty" />
<Constraint
android:id="@id/text_balance_includes_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@id/space_left_icon"
motion:layout_constraintBottom_toTopOf="@id/image_zec_symbol_balance"/>
<Constraint
android:id="@id/text_balance_usd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@id/image_zec_symbol_balance"/>
<Constraint
android:id="@id/text_balance_zec_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="42dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintBottom_toBottomOf="parent"/>
</ConstraintSet>
<ConstraintSet android:id="@id/end">
<Constraint
android:id="@id/space_left_icon"
android:layout_width="64dp"
android:layout_height="?attr/actionBarSize"
motion:layout_constraintBottom_toBottomOf="parent" />
<Constraint
android:id="@id/home_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent" />
<Constraint
android:id="@id/text_balance_zec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="@id/space_left_icon"
motion:layout_constraintStart_toEndOf="@id/space_left_icon"
motion:layout_constraintTop_toTopOf="@id/space_left_icon">
<CustomAttribute
motion:attributeName="textSize"
motion:customFloatValue="24.0" />
</Constraint>
<Constraint
android:id="@id/text_balance_zec_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha='0.0'
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent"
motion:layout_constraintVertical_bias="0.36"/>
<Constraint
android:id="@id/image_zec_symbol_balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginRight="0dp"
android:scaleX="0.4"
android:scaleY="0.4"
android:alpha="1.0"
motion:layout_constraintEnd_toStartOf="@id/text_balance_zec"
motion:layout_constraintTop_toTopOf="@id/text_balance_zec" />
<Constraint
android:id="@id/image_zec_symbol_balance_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:alpha="1.0"
android:scaleX="0.4"
android:scaleY="0.4"
motion:layout_constraintStart_toStartOf="@id/image_zec_symbol_balance"
motion:layout_constraintTop_toTopOf="@+id/image_zec_symbol_balance" />
<Constraint
android:id="@id/image_zec_symbol_balance_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
android:alpha="0.0"
motion:layout_constraintEnd_toStartOf="@id/text_balance_zec_empty"
motion:layout_constraintTop_toTopOf="@id/text_balance_zec_empty" />
<Constraint
android:id="@id/image_zec_symbol_balance_shadow_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:alpha="0.0"
motion:layout_constraintStart_toStartOf="@id/image_zec_symbol_balance_empty"
motion:layout_constraintTop_toTopOf="@+id/image_zec_symbol_balance_empty" />
<Constraint
android:id="@id/text_balance_includes_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.0"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@id/space_left_icon"
motion:layout_constraintBottom_toTopOf="@id/image_zec_symbol_balance"/>
<Constraint
android:id="@id/text_balance_usd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:alpha="0.0"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@id/image_zec_symbol_balance"/>
<Constraint
android:id="@id/text_balance_zec_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="42dp"
android:alpha="0.0"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintBottom_toBottomOf="parent"/>
</ConstraintSet>
<KeyFrameSet>
<KeyPosition
motion:curveFit="spline"
motion:framePosition="80"
motion:keyPositionType="deltaRelative"
motion:pathMotionArc="startVertical"
motion:percentX="0.36"
motion:target="@id/text_balance_zec" />
<KeyPosition
motion:curveFit="spline"
motion:framePosition="88"
motion:keyPositionType="deltaRelative"
motion:pathMotionArc="startVertical"
motion:percentX="0.38"
motion:target="@id/image_zec_symbol_balance" />
<KeyPosition
motion:curveFit="spline"
motion:framePosition="88"
motion:keyPositionType="deltaRelative"
motion:pathMotionArc="startVertical"
motion:percentX="0.38"
motion:target="@id/image_zec_symbol_balance_shadow" />
<KeyAttribute
android:alpha="0.0"
motion:framePosition="10"
motion:target="@id/image_zec_symbol_balance_empty" />
<KeyAttribute
android:alpha="0.0"
motion:framePosition="10"
motion:target="@id/image_zec_symbol_balance_shadow_empty" />
<KeyAttribute
android:alpha="0.0"
motion:framePosition="10"
motion:target="@id/text_balance_includes_info" />
<KeyAttribute
android:alpha="0.0"
motion:framePosition="10"
motion:target="@id/text_balance_zec_empty" />
<KeyAttribute
android:alpha="0.0"
motion:framePosition="10"
motion:target="@id/text_balance_usd" />
<KeyAttribute
android:alpha="0.0"
motion:framePosition="10"
motion:target="@id/text_balance_zec_info" />
</KeyFrameSet>
</Transition>
</MotionScene>

View File

@ -40,7 +40,7 @@ buildscript {
'material': 'com.google.android.material:material:1.0.0',
'speeddial': 'com.leinardi.android:speed-dial:2.0.0',
'zcash': [
'walletSdk': "cash.z.android.wallet:zcash-android-wallet-sdk:1.2.0"
'walletSdk': "cash.z.android.wallet:zcash-android-wallet-sdk:1.2.3@aar"
]
]
repositories {
@ -58,6 +58,9 @@ buildscript {
allprojects {
repositories {
mavenLocal()
flatDir {
dirs 'libs'
}
google()
jcenter()

View File

@ -8,7 +8,8 @@ import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType.ERROR_CORRECTION
import com.google.zxing.EncodeHintType.MARGIN
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.Q
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.*
class QRecycler {
@ -21,7 +22,7 @@ class QRecycler {
builder.target.doOnLayout { measuredView ->
val w = measuredView.width
val h = measuredView.height
val hints = mapOf(ERROR_CORRECTION to Q, MARGIN to 2)
val hints = mapOf(ERROR_CORRECTION to builder.errorCorrection, MARGIN to builder.quietZone)
val bitMatrix = QRCodeWriter().encode(builder.content, BarcodeFormat.QR_CODE, w, h, hints)
val pixels = IntArray(w * h)
for (y in 0 until h) {
@ -39,9 +40,23 @@ class QRecycler {
inner class Builder(val content: String) {
lateinit var target: ImageView
var errorCorrection: ErrorCorrectionLevel = Q
var quietZone: Int = 4
fun into(imageView: ImageView) {
target = imageView
encode(this)
}
fun withQuietZoneSize(customQuietZone: Int): Builder {
quietZone = customQuietZone
return this
}
fun withCorrectionLevel(level: CorrectionLevel): Builder {
errorCorrection = level.errorCorrectionLevel
return this
}
}
enum class CorrectionLevel(val errorCorrectionLevel: ErrorCorrectionLevel) {
LOW(L), DEFAULT(M), MEDIUM(Q), HIGH(H);
}
}