From ff2a58bcf8ed3d0d61f2ff8ef680fcab82cb012d Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Mon, 9 Jul 2018 18:33:42 -0500 Subject: [PATCH 01/41] Improve Contact elements layout --- .../fragments/ContactsFragment.java | 3 +- .../views/ContactViewHolder.java | 3 +- app/src/main/res/layout/contact_list.xml | 2 + app/src/main/res/layout/contact_list_item.xml | 80 ++++++++++--------- app/src/main/res/values/dimens.xml | 18 +---- 5 files changed, 51 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java index 6f34284..0e06790 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java @@ -5,6 +5,7 @@ import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.arch.paging.PagedList; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -40,7 +41,7 @@ public class ContactsFragment extends Fragment { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View v = inflater.inflate(R.layout.fragment_contacts, container, false); diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java b/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java index 376ce11..b37ce0a 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java +++ b/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java @@ -78,7 +78,8 @@ public class ContactViewHolder extends RecyclerView.ViewHolder { Picasso.with(this.context) .load(gravatarUrl) - .transform(new CircleTransformation()) + .placeholder(R.drawable.avatar_placeholder) + //.transform(new CircleTransformation()) .into(ivThumbnail); } diff --git a/app/src/main/res/layout/contact_list.xml b/app/src/main/res/layout/contact_list.xml index fc6edac..766952f 100644 --- a/app/src/main/res/layout/contact_list.xml +++ b/app/src/main/res/layout/contact_list.xml @@ -1,6 +1,7 @@ @@ -9,5 +10,6 @@ android:id="@+id/contactListView" android:layout_width="match_parent" android:layout_height="wrap_content" + tools:listitem="@layout/contact_list_item" /> \ No newline at end of file diff --git a/app/src/main/res/layout/contact_list_item.xml b/app/src/main/res/layout/contact_list_item.xml index 2beaec2..379419e 100644 --- a/app/src/main/res/layout/contact_list_item.xml +++ b/app/src/main/res/layout/contact_list_item.xml @@ -1,47 +1,53 @@ - + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp"> - + + + android:layout_marginTop="8dp" + android:layout_marginStart="16dp" + tools:text="Loading name..." + android:textAppearance="@style/TextAppearance.Body1" + android:textStyle="bold" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toEndOf="@id/ivContactThumbnail"/> - + - + - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b81577a..5cbaff4 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -2,24 +2,10 @@ 16dp 16dp - 264dp - 16dp - 14sp - 72dp + 140sp 16dp - 16dp - 35sp - 30sp - 5dp - 70dp - 140dp - 150dp - 8dp - - - 13sp - 70dp + 60dp From 7e51385dc0e9597b313b389e1c520d1e83cf28a3 Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Tue, 10 Jul 2018 16:19:10 -0500 Subject: [PATCH 02/41] Simplify Contacts section --- .../fragments/ContactsFragment.java | 28 +++-- .../viewmodels/ContactListViewModel.java | 10 -- .../crystalwallet/views/ContactListView.java | 111 ------------------ app/src/main/res/layout/fragment_contacts.xml | 5 +- 4 files changed, 22 insertions(+), 132 deletions(-) delete mode 100644 app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java index 0e06790..54f69cd 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java @@ -8,6 +8,8 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -17,12 +19,14 @@ import butterknife.ButterKnife; import cy.agorise.crystalwallet.R; import cy.agorise.crystalwallet.models.Contact; import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; -import cy.agorise.crystalwallet.views.ContactListView; +import cy.agorise.crystalwallet.views.ContactListAdapter; public class ContactsFragment extends Fragment { - @BindView(R.id.vContactListView) - ContactListView contactListView; + @BindView(R.id.recyclerViewContacts) + RecyclerView recyclerViewContacts; + + ContactListAdapter adapter; public ContactsFragment() { // Required empty public constructor @@ -44,20 +48,26 @@ public class ContactsFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - View v = inflater.inflate(R.layout.fragment_contacts, container, false); - ButterKnife.bind(this, v); + View view = inflater.inflate(R.layout.fragment_contacts, container, false); + ButterKnife.bind(this, view); - ContactListViewModel contactListViewModel = ViewModelProviders.of(this).get(ContactListViewModel.class); - contactListViewModel.init(); + // Configure RecyclerView and its adapter + recyclerViewContacts.setLayoutManager(new LinearLayoutManager(getContext())); + adapter = new ContactListAdapter(); + recyclerViewContacts.setAdapter(adapter); + + // Gets contacts LiveData instance from ContactsViewModel + ContactListViewModel contactListViewModel = + ViewModelProviders.of(this).get(ContactListViewModel.class); LiveData> contactsLiveData = contactListViewModel.getContactList(); contactsLiveData.observe(this, new Observer>() { @Override public void onChanged(@Nullable PagedList contacts) { - contactListView.setData(contacts); + adapter.submitList(contacts); } }); - return v; + return view; } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java index 51c3836..5a1a512 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java @@ -32,16 +32,6 @@ public class ContactListViewModel extends AndroidViewModel { ).build(); } - public void init(){ - contactList = new LivePagedListBuilder(this.db.contactDao().contactsByName(), - new PagedList.Config.Builder() - .setEnablePlaceholders(true) - .setPageSize(10) - .setPrefetchDistance(10) - .build() - ).build(); - } - public void init(CryptoNet cryptoNet){ contactList = new LivePagedListBuilder(this.db.contactDao().contactsByNameAndCryptoNet(cryptoNet.name()), new PagedList.Config.Builder() diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java b/app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java deleted file mode 100644 index 37d5cfa..0000000 --- a/app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java +++ /dev/null @@ -1,111 +0,0 @@ -package cy.agorise.crystalwallet.views; - -import android.arch.paging.PagedList; -import android.content.Context; -import android.support.v4.app.Fragment; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.RelativeLayout; - -import cy.agorise.crystalwallet.R; -import cy.agorise.crystalwallet.models.Contact; -import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; - -/** - * Created by Henry Varona on 1/15/2018. - * - * A list view showing the user contacts - */ - -public class ContactListView extends RelativeLayout { - - LayoutInflater mInflater; - - /* - * The root view of this view - */ - View rootView; - /* - * The list view that holds every user contact item - */ - RecyclerView listView; - /* - * The adapter for the previous list view - */ - ContactListAdapter listAdapter; - - ContactListViewModel contactListViewModel; - - /* - * how much contacts will remain to show before the list loads more - */ - private int visibleThreshold = 5; - /* - * if true, the contact list will be loading new data - */ - private boolean loading = true; - - /* - * One of three constructors needed to be inflated from a layout - */ - public ContactListView(Context context){ - super(context); - this.mInflater = LayoutInflater.from(context); - init(); - } - - /* - * One of three constructors needed to be inflated from a layout - */ - public ContactListView(Context context, AttributeSet attrs) { - super(context, attrs); - this.mInflater = LayoutInflater.from(context); - init(); - } - - /* - * One of three constructors needed to be inflated from a layout - */ - public ContactListView(Context context, AttributeSet attrs, int defStyle){ - super(context, attrs, defStyle); - this.mInflater = LayoutInflater.from(context); - init(); - } - - /* - * Initializes this view - */ - public void init(){ - rootView = mInflater.inflate(R.layout.contact_list, this, true); - this.listView = rootView.findViewById(R.id.contactListView); - - final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this.getContext()); - this.listView.setLayoutManager(linearLayoutManager); - //Prevents the list to start again when scrolling to the end - //this.listView.setNestedScrollingEnabled(false); - - } - - /* - * Sets the elements data of this view - * - * @param data the contacts that will be showed to the user - */ - public void setData(PagedList data){ - //Initializes the adapter of the contact list - if (this.listAdapter == null) { - this.listAdapter = new ContactListAdapter(); - this.listView.setAdapter(this.listAdapter); - } - - //Sets the data of the transaction list - if (data != null) { - this.listAdapter.submitList(data); - } - } - - -} diff --git a/app/src/main/res/layout/fragment_contacts.xml b/app/src/main/res/layout/fragment_contacts.xml index 95a3da7..043bf37 100644 --- a/app/src/main/res/layout/fragment_contacts.xml +++ b/app/src/main/res/layout/fragment_contacts.xml @@ -4,9 +4,10 @@ android:layout_height="match_parent" tools:context="cy.agorise.crystalwallet.fragments.ContactsFragment"> - + tools:listitem="@layout/contact_list_item" /> From 99a4dc254d9e72eeec917f789ae6b4616789ae7a Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Tue, 10 Jul 2018 17:43:40 -0500 Subject: [PATCH 03/41] Add bounce effect to contacts list --- .../fragments/ContactsFragment.java | 59 +++- .../util/BounceTouchListener.java | 307 ++++++++++++++++++ app/src/main/res/layout/fragment_contacts.xml | 2 +- 3 files changed, 363 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/cy/agorise/crystalwallet/util/BounceTouchListener.java diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java index 54f69cd..e141f91 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java @@ -1,15 +1,18 @@ package cy.agorise.crystalwallet.fragments; +import android.app.Activity; import android.arch.lifecycle.LiveData; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.arch.paging.PagedList; +import android.graphics.Point; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,16 +21,21 @@ import butterknife.BindView; import butterknife.ButterKnife; import cy.agorise.crystalwallet.R; import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.util.BounceTouchListener; import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; import cy.agorise.crystalwallet.views.ContactListAdapter; public class ContactsFragment extends Fragment { - @BindView(R.id.recyclerViewContacts) - RecyclerView recyclerViewContacts; + @BindView(R.id.rvContacts) + RecyclerView rvContacts; ContactListAdapter adapter; + // Fields used to achieve bounce effect while over-scrolling the contacts list + private BounceTouchListener bounceTouchListener; + float pivotY1, pivotY2; + public ContactsFragment() { // Required empty public constructor } @@ -52,9 +60,11 @@ public class ContactsFragment extends Fragment { ButterKnife.bind(this, view); // Configure RecyclerView and its adapter - recyclerViewContacts.setLayoutManager(new LinearLayoutManager(getContext())); + rvContacts.setLayoutManager(new LinearLayoutManager(getContext())); adapter = new ContactListAdapter(); - recyclerViewContacts.setAdapter(adapter); + rvContacts.setAdapter(adapter); + + configureListBounceEffect(); // Gets contacts LiveData instance from ContactsViewModel ContactListViewModel contactListViewModel = @@ -70,4 +80,45 @@ public class ContactsFragment extends Fragment { return view; } + + private void configureListBounceEffect() { + rvContacts.setPivotX(getScreenWidth(getActivity()) * 0.5f); + + pivotY1 = 0; + pivotY2 = (getScreenHeight(getActivity())) * .5f; + + bounceTouchListener = BounceTouchListener.create(rvContacts, new BounceTouchListener.OnTranslateListener() { + @Override + public void onTranslate(float translation) { + if(translation > 0) { + bounceTouchListener.setMaxAbsTranslation(-99); + rvContacts.setPivotY(pivotY1); + float scale = ((2 * translation) / rvContacts.getMeasuredHeight()) + 1; + rvContacts.setScaleY((float) Math.pow(scale, .6f)); + } else { + bounceTouchListener.setMaxAbsTranslation((int) (pivotY2 * .33f)); + rvContacts.setPivotY(pivotY2); + float scale = ((2 * translation) / rvContacts.getMeasuredHeight()) + 1; + rvContacts.setScaleY((float) Math.pow(scale, .5f)); + } + } + }); + + // Sets custom touch listener to handle bounce/stretch effect + rvContacts.setOnTouchListener(bounceTouchListener); + } + + public static int getScreenWidth(Activity activity) { + Display display = activity.getWindowManager().getDefaultDisplay(); + Point size = new Point(); + display.getSize(size); + return size.x; + } + + public static int getScreenHeight(Activity activity) { + Display display = activity.getWindowManager().getDefaultDisplay(); + Point size = new Point(); + display.getSize(size); + return size.y; + } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/util/BounceTouchListener.java b/app/src/main/java/cy/agorise/crystalwallet/util/BounceTouchListener.java new file mode 100644 index 0000000..4053ad9 --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/util/BounceTouchListener.java @@ -0,0 +1,307 @@ +package cy.agorise.crystalwallet.util; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.support.annotation.IdRes; +import android.support.annotation.Nullable; +import android.support.v4.view.MotionEventCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; +import android.widget.ListView; +import android.widget.ScrollView; + +/** + * Found this class on the internet and did some changes do adjust it to our + * needs but I still need to figure out some stuff to obtain the exact desired + * animation + */ + +public class BounceTouchListener implements View.OnTouchListener { + private static final long DEFAULT_ANIMATION_TIME = 600L; + + private boolean downCalled = false; + private OnTranslateListener onTranslateListener; + private View mMainView; + private View mContent; + private float mDownY; + private boolean mSwipingDown; + private boolean mSwipingUp; + private Interpolator mInterpolator = new DecelerateInterpolator(3f); + private boolean swipeUpEnabled = true; + private int mActivePointerId = -99; + private float mLastTouchY = -99; + private int mMaxAbsTranslation = -99; + + + private BounceTouchListener(View mainView, int contentResId, @Nullable OnTranslateListener listener) { + mMainView = mainView; + mContent = (contentResId == -1) ? mMainView : mMainView.findViewById(contentResId); + onTranslateListener = listener; + } + + /** + * Creates a new BounceTouchListener + * + * @param mainScrollableView The main view that this touch listener is attached to + * @param onTranslateListener To perform action on translation, can be null if not needed + * @return A new BounceTouchListener attached to the given scrollable view + */ + public static BounceTouchListener create(View mainScrollableView, @Nullable OnTranslateListener onTranslateListener) { + return create(mainScrollableView, -1, onTranslateListener); + } + + /** + * Creates a new BounceTouchListener + * + * @param mainView The main view that this touch listener is attached to + * @param contentResId Resource Id of the scrollable view + * @param onTranslateListener To perform action on translation, can be null if not needed + * @return A new BounceTouchListener attached to the given scrollable view + */ + public static BounceTouchListener create(View mainView, @IdRes int contentResId, + @Nullable OnTranslateListener onTranslateListener) { + return new BounceTouchListener(mainView, contentResId, onTranslateListener); + } + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + final int action = MotionEventCompat.getActionMasked(motionEvent); + + switch (action) { + case MotionEvent.ACTION_DOWN: { + onDownMotionEvent(motionEvent); + view.onTouchEvent(motionEvent); + downCalled = true; + if (mContent.getTranslationY() == 0) { + return false; + } + } + case MotionEvent.ACTION_MOVE: { + if (mActivePointerId == -99) { + onDownMotionEvent(motionEvent); + downCalled = true; + } + final int pointerIndex = + MotionEventCompat.findPointerIndex(motionEvent, mActivePointerId); + final float y = MotionEventCompat.getY(motionEvent, pointerIndex); + + if (!hasHitTop() && !hasHitBottom() || !downCalled) { + if (!downCalled) { + downCalled = true; + } + mDownY = y; + view.onTouchEvent(motionEvent); + return false; + } + + float deltaY = y - mDownY; + if (Math.abs(deltaY) > 0 && hasHitTop() && deltaY > 0) { + mSwipingDown = true; + sendCancelEventToView(view, motionEvent); + } + if (swipeUpEnabled) { + if (Math.abs(deltaY) > 0 && hasHitBottom() && deltaY < 0) { + mSwipingUp = true; + sendCancelEventToView(view, motionEvent); + } + } + if (mSwipingDown || mSwipingUp) { + if ((deltaY <= 0 && mSwipingDown) || (deltaY >= 0 && mSwipingUp)) { + mDownY = 0; + mSwipingDown = false; + mSwipingUp = false; + downCalled = false; + MotionEvent downEvent = MotionEvent.obtain(motionEvent); + downEvent.setAction(MotionEvent.ACTION_DOWN | + (MotionEventCompat.getActionIndex(motionEvent) << MotionEventCompat.ACTION_POINTER_INDEX_SHIFT)); + view.onTouchEvent(downEvent); + break; + } + int translation = (int) ((deltaY / Math.abs(deltaY)) * Math.pow(Math.abs(deltaY), .8f)); + if (mMaxAbsTranslation > 0) { + if (translation < 0) { + translation = Math.max(-mMaxAbsTranslation, translation); + } else { + translation = Math.min(mMaxAbsTranslation, translation); + } + } + mContent.setTranslationY(translation); + if (onTranslateListener != null) + onTranslateListener.onTranslate(mContent.getTranslationY()); + + return true; + } + break; + } + + case MotionEvent.ACTION_UP: { + mActivePointerId = -99; + // cancel + mContent.animate() + .setInterpolator(mInterpolator) + .translationY(0) + .setDuration(DEFAULT_ANIMATION_TIME) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + ((ValueAnimator) animation).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + if (onTranslateListener != null) { + onTranslateListener.onTranslate(mContent.getTranslationY()); + } + } + }); + super.onAnimationStart(animation); + } + }); + + mDownY = 0; + mSwipingDown = false; + mSwipingUp = false; + downCalled = false; + break; + } + + case MotionEvent.ACTION_CANCEL: { + mActivePointerId = -99; + break; + } + + case MotionEvent.ACTION_POINTER_UP: { + final int pointerIndex = MotionEventCompat.getActionIndex(motionEvent); + final int pointerId = MotionEventCompat.getPointerId(motionEvent, pointerIndex); + + if (pointerId == mActivePointerId) { + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mLastTouchY = MotionEventCompat.getY(motionEvent, newPointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(motionEvent, newPointerIndex); + + if (mContent.getTranslationY() > 0) { + mDownY = mLastTouchY - (int) Math.pow(mContent.getTranslationY(), 10f / 8f); + mContent.animate().cancel(); + } else if (mContent.getTranslationY() < 0) { + mDownY = mLastTouchY + (int) Math.pow(-mContent.getTranslationY(), 10f / 8f); + mContent.animate().cancel(); + } + } + break; + } + } + return false; + } + + private void sendCancelEventToView(View view, MotionEvent motionEvent) { + ((ViewGroup) view).requestDisallowInterceptTouchEvent(true); + MotionEvent cancelEvent = MotionEvent.obtain(motionEvent); + cancelEvent.setAction(MotionEvent.ACTION_CANCEL | + (MotionEventCompat.getActionIndex(motionEvent) << MotionEventCompat.ACTION_POINTER_INDEX_SHIFT)); + view.onTouchEvent(cancelEvent); + } + + private void onDownMotionEvent(MotionEvent motionEvent) { + final int pointerIndex = MotionEventCompat.getActionIndex(motionEvent); + mLastTouchY = MotionEventCompat.getY(motionEvent, pointerIndex); + mActivePointerId = MotionEventCompat.getPointerId(motionEvent, 0); + + if (mContent.getTranslationY() > 0) { + mDownY = mLastTouchY - (int) Math.pow(mContent.getTranslationY(), 10f / 8f); + mContent.animate().cancel(); + } else if (mContent.getTranslationY() < 0) { + mDownY = mLastTouchY + (int) Math.pow(-mContent.getTranslationY(), 10f / 8f); + mContent.animate().cancel(); + } else { + mDownY = mLastTouchY; + } + } + + private boolean hasHitBottom() { + if (mMainView instanceof ScrollView) { + ScrollView scrollView = (ScrollView) mMainView; + View view = scrollView.getChildAt(scrollView.getChildCount() - 1); + int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));// Calculate the scrolldiff + return diff == 0; + } else if (mMainView instanceof ListView) { + ListView listView = (ListView) mMainView; + if (listView.getAdapter() != null) { + if (listView.getAdapter().getCount() > 0) { + return listView.getLastVisiblePosition() == listView.getAdapter().getCount() - 1 && + listView.getChildAt(listView.getChildCount() - 1).getBottom() <= listView.getHeight(); + } + } + } else if (mMainView instanceof RecyclerView) { + RecyclerView recyclerView = (RecyclerView) mMainView; + if (recyclerView.getAdapter() != null && recyclerView.getLayoutManager() != null) { + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter.getItemCount() > 0) { + RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + if (layoutManager instanceof LinearLayoutManager) { + LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; + return linearLayoutManager.findLastCompletelyVisibleItemPosition() == adapter.getItemCount() - 1; + } else if (layoutManager instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager; + int[] checks = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(null); + for (int check : checks) { + if (check == adapter.getItemCount() - 1) + return true; + } + } + } + } + } + return false; + } + + private boolean hasHitTop() { + if (mMainView instanceof ScrollView) { + ScrollView scrollView = (ScrollView) mMainView; + return scrollView.getScrollY() == 0; + } else if (mMainView instanceof ListView) { + ListView listView = (ListView) mMainView; + if (listView.getAdapter() != null) { + if (listView.getAdapter().getCount() > 0) { + return listView.getFirstVisiblePosition() == 0 && + listView.getChildAt(0).getTop() >= 0; + } + } + } else if (mMainView instanceof RecyclerView) { + RecyclerView recyclerView = (RecyclerView) mMainView; + if (recyclerView.getAdapter() != null && recyclerView.getLayoutManager() != null) { + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter.getItemCount() > 0) { + RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + if (layoutManager instanceof LinearLayoutManager) { + LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; + return linearLayoutManager.findFirstCompletelyVisibleItemPosition() == 0; + } else if (layoutManager instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager; + int[] checks = staggeredGridLayoutManager.findFirstCompletelyVisibleItemPositions(null); + for (int check : checks) { + if (check == 0) + return true; + } + } + } + } + } + + return false; + } + + public void setMaxAbsTranslation(int maxAbsTranslation) { + this.mMaxAbsTranslation = maxAbsTranslation; + } + + public interface OnTranslateListener { + void onTranslate(float translation); + } +} + + diff --git a/app/src/main/res/layout/fragment_contacts.xml b/app/src/main/res/layout/fragment_contacts.xml index 043bf37..c2147c1 100644 --- a/app/src/main/res/layout/fragment_contacts.xml +++ b/app/src/main/res/layout/fragment_contacts.xml @@ -5,7 +5,7 @@ tools:context="cy.agorise.crystalwallet.fragments.ContactsFragment"> From 656ce4afb239a58097bc639697427bb9f1d2f3ee Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Wed, 11 Jul 2018 12:41:00 -0500 Subject: [PATCH 04/41] Terminate Intro and License activities when starting the following activities to avoid memory leaks --- .../cy/agorise/crystalwallet/activities/IntroActivity.java | 4 +--- .../cy/agorise/crystalwallet/activities/LicenseActivity.java | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java index e95513e..d81e79f 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java @@ -37,9 +37,6 @@ import cy.agorise.crystalwallet.views.TransactionListView; public class IntroActivity extends AppCompatActivity { - TransactionListViewModel transactionListViewModel; - TransactionListView transactionListView; - @BindView(R.id.surface_view) public SurfaceView mSurfaceView; @@ -96,6 +93,7 @@ public class IntroActivity extends AppCompatActivity { //Intent intent = new Intent(this, CreateSeedActivity.class); Intent intent = new Intent(this, BoardActivity.class); startActivity(intent); + finish(); } /*CrystalDatabase db = CrystalDatabase.getAppDatabase(getApplicationContext()); diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java index 8964738..fc52b6f 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java @@ -37,6 +37,7 @@ public class LicenseActivity extends AppCompatActivity { if ((generalSettingLastLicenseRead != null) && (Integer.parseInt(generalSettingLastLicenseRead.getValue()) >= licenseVersion)) { Intent intent = new Intent(this, IntroActivity.class); startActivity(intent); + finish(); } } @@ -52,6 +53,7 @@ public class LicenseActivity extends AppCompatActivity { Intent intent = new Intent(this, IntroActivity.class); startActivity(intent); + finish(); } @OnClick(R.id.btnDisAgree) From b3501a3a897c9266304414c2a767fd1d6ee530bf Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Wed, 11 Jul 2018 13:23:54 -0500 Subject: [PATCH 05/41] Remove contacts list bouncy efect for now --- .../fragments/ContactsFragment.java | 51 ------------------- app/src/main/res/layout/board.xml | 5 +- 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java index e141f91..3d9d608 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java @@ -1,18 +1,15 @@ package cy.agorise.crystalwallet.fragments; -import android.app.Activity; import android.arch.lifecycle.LiveData; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.arch.paging.PagedList; -import android.graphics.Point; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,7 +18,6 @@ import butterknife.BindView; import butterknife.ButterKnife; import cy.agorise.crystalwallet.R; import cy.agorise.crystalwallet.models.Contact; -import cy.agorise.crystalwallet.util.BounceTouchListener; import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; import cy.agorise.crystalwallet.views.ContactListAdapter; @@ -32,10 +28,6 @@ public class ContactsFragment extends Fragment { ContactListAdapter adapter; - // Fields used to achieve bounce effect while over-scrolling the contacts list - private BounceTouchListener bounceTouchListener; - float pivotY1, pivotY2; - public ContactsFragment() { // Required empty public constructor } @@ -64,8 +56,6 @@ public class ContactsFragment extends Fragment { adapter = new ContactListAdapter(); rvContacts.setAdapter(adapter); - configureListBounceEffect(); - // Gets contacts LiveData instance from ContactsViewModel ContactListViewModel contactListViewModel = ViewModelProviders.of(this).get(ContactListViewModel.class); @@ -80,45 +70,4 @@ public class ContactsFragment extends Fragment { return view; } - - private void configureListBounceEffect() { - rvContacts.setPivotX(getScreenWidth(getActivity()) * 0.5f); - - pivotY1 = 0; - pivotY2 = (getScreenHeight(getActivity())) * .5f; - - bounceTouchListener = BounceTouchListener.create(rvContacts, new BounceTouchListener.OnTranslateListener() { - @Override - public void onTranslate(float translation) { - if(translation > 0) { - bounceTouchListener.setMaxAbsTranslation(-99); - rvContacts.setPivotY(pivotY1); - float scale = ((2 * translation) / rvContacts.getMeasuredHeight()) + 1; - rvContacts.setScaleY((float) Math.pow(scale, .6f)); - } else { - bounceTouchListener.setMaxAbsTranslation((int) (pivotY2 * .33f)); - rvContacts.setPivotY(pivotY2); - float scale = ((2 * translation) / rvContacts.getMeasuredHeight()) + 1; - rvContacts.setScaleY((float) Math.pow(scale, .5f)); - } - } - }); - - // Sets custom touch listener to handle bounce/stretch effect - rvContacts.setOnTouchListener(bounceTouchListener); - } - - public static int getScreenWidth(Activity activity) { - Display display = activity.getWindowManager().getDefaultDisplay(); - Point size = new Point(); - display.getSize(size); - return size.x; - } - - public static int getScreenHeight(Activity activity) { - Display display = activity.getWindowManager().getDefaultDisplay(); - Point size = new Point(); - display.getSize(size); - return size.y; - } } diff --git a/app/src/main/res/layout/board.xml b/app/src/main/res/layout/board.xml index 8e0b8e4..b53fe90 100644 --- a/app/src/main/res/layout/board.xml +++ b/app/src/main/res/layout/board.xml @@ -3,16 +3,15 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" + android:fitsSystemWindows="true" tools:context=".activities.BoardActivity"> @@ -102,7 +101,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_collapseMode="pin" - android:animateLayoutChanges="true" /> + app:tabIndicatorHeight="0dp"/> From bd0bbfa8023c08b29ac300986685425564e70160 Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Wed, 11 Jul 2018 16:51:15 -0500 Subject: [PATCH 06/41] Hide add contact button when scrolling down the contacts list --- .../activities/BoardActivity.java | 2 -- .../fragments/ContactsFragment.java | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java index c9f5a16..6767fa1 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java @@ -26,8 +26,6 @@ import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.ImageView; -import com.sjaramillo10.animatedtablayout.AnimatedTabLayout; - import java.io.File; import butterknife.BindView; diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java index 3d9d608..d17c179 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java @@ -7,6 +7,7 @@ import android.arch.paging.PagedList; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -28,6 +29,8 @@ public class ContactsFragment extends Fragment { ContactListAdapter adapter; + FloatingActionButton fabAddContact; + public ContactsFragment() { // Required empty public constructor } @@ -56,6 +59,24 @@ public class ContactsFragment extends Fragment { adapter = new ContactListAdapter(); rvContacts.setAdapter(adapter); + fabAddContact = getActivity().findViewById(R.id.fabAddContact); + + // Hides the fab when scrolling down + rvContacts.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + + // Scroll down + if(dy > 0 && fabAddContact.isShown()) + fabAddContact.hide(); + + // Scroll up + if(dy < 0 && !fabAddContact.isShown()) + fabAddContact.show(); + } + }); + // Gets contacts LiveData instance from ContactsViewModel ContactListViewModel contactListViewModel = ViewModelProviders.of(this).get(ContactListViewModel.class); From 3008415316331da63f05e87515c228c7825924d5 Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Thu, 12 Jul 2018 10:32:01 -0500 Subject: [PATCH 07/41] Improve create/modify contact UI --- .../activities/CreateContactActivity.java | 126 +++++----- .../validators/CreateContactValidator.java | 3 +- .../validators/ModifyContactValidator.java | 3 +- app/src/main/res/layout/activity_account.xml | 146 ----------- .../res/layout/activity_create_contact.xml | 228 ++++++------------ .../res/layout/activity_existing_account.xml | 34 --- .../res/layout/contact_address_list_item.xml | 29 +-- app/src/main/res/layout/create_seed.xml | 40 --- app/src/main/res/values/dimens.xml | 5 + app/src/main/res/values/strings.xml | 4 +- app/src/main/res/values/styles.xml | 14 +- 11 files changed, 152 insertions(+), 480 deletions(-) delete mode 100644 app/src/main/res/layout/activity_account.xml delete mode 100644 app/src/main/res/layout/activity_existing_account.xml diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java index 0791d40..373d41c 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java @@ -4,15 +4,14 @@ import android.arch.lifecycle.LiveData; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.support.annotation.Nullable; +import android.support.design.widget.TextInputEditText; +import android.support.design.widget.TextInputLayout; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.text.Editable; import android.view.View; import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; import java.util.ArrayList; import java.util.List; @@ -33,20 +32,14 @@ import cy.agorise.crystalwallet.views.ContactAddressListAdapter; public class CreateContactActivity extends AppCompatActivity implements UIValidatorListener { - @BindView(R.id.etName) - EditText etName; - @BindView(R.id.tvNameError) - TextView tvNameError; - @BindView(R.id.etEmail) - EditText etEmail; - @BindView(R.id.tvEmailError) - TextView tvEmailError; + @BindView(R.id.tilName) + TextInputLayout tilName; + @BindView(R.id.tietName) + TextInputEditText tietName; @BindView(R.id.btnCancel) Button btnCancel; @BindView(R.id.btnCreate) Button btnCreate; - @BindView(R.id.btnModify) - Button btnModify; @BindView(R.id.rvContactAddresses) RecyclerView rvContactAddresses; @BindView(R.id.btnAddAddress) @@ -59,6 +52,8 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida Contact contact; + long contactId; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -71,10 +66,7 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida rvContactAddresses.setLayoutManager(new LinearLayoutManager(getApplicationContext())); rvContactAddresses.setAdapter(listAdapter); - long contactId = this.getIntent().getLongExtra("CONTACT_ID",-1); - - btnCreate.setVisibility(View.GONE); - btnModify.setVisibility(View.GONE); + contactId = getIntent().getLongExtra("CONTACT_ID",-1); if (contactId >= 0){ final ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); @@ -88,8 +80,7 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida public void onChanged(@Nullable Contact contactChanged) { if (contactChanged != null){ contact = contactChanged; - etName.setText(contact.getName()); - etEmail.setText(contact.getEmail()); + tietName.setText(contact.getName()); LiveData> contactAddresses = contactViewModel.getContactAddresses(); @@ -102,9 +93,10 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida } }); - modifyContactValidator = new ModifyContactValidator(thisActivity.getApplicationContext(),contact,etName,etEmail); + modifyContactValidator = new ModifyContactValidator( + thisActivity.getApplicationContext(), contact, tietName); modifyContactValidator.setListener(thisActivity); - btnModify.setVisibility(View.VISIBLE); + btnCreate.setText(R.string.modify); } else { //No contact was found, this will exit the activity finish(); @@ -112,9 +104,9 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida } }); } else { - contactAddressList = new ArrayList(); + contactAddressList = new ArrayList<>(); listAdapter.submitList(contactAddressList); - createContactValidator = new CreateContactValidator(this.getApplicationContext(),etName,etEmail); + createContactValidator = new CreateContactValidator(this.getApplicationContext(),tietName); createContactValidator.setListener(this); btnCreate.setVisibility(View.VISIBLE); @@ -139,19 +131,12 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida return false; } - @OnTextChanged(value = R.id.etName, + @OnTextChanged(value = R.id.tietName, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) - void afterContactNameChanged(Editable editable) { + void afterContactNameChanged() { this.validate(); } - @OnTextChanged(value = R.id.etEmail, - callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) - void afterEmailChanged(Editable editable) { - this.validate(); - } - - @OnClick(R.id.btnAddAddress) public void addAddress(){ ContactAddress newContactAddress = new ContactAddress(); @@ -164,42 +149,43 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida this.finish(); } - @OnClick(R.id.btnModify) - public void modifyContact(){ - if (this.modifyContactValidator.isValid()) { - this.contact.setName(etName.getText().toString()); - this.contact.setEmail(etEmail.getText().toString()); - this.contact.clearAddresses(); - - for (ContactAddress contactAddress : contactAddressList){ - this.contact.addAddress(contactAddress); - } - - ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); - if (contactViewModel.modifyContact(this.contact)){ - this.finish(); - } else { - this.modifyContactValidator.validate(); - } - } - } - @OnClick(R.id.btnCreate) - public void createContact(){ - if (this.createContactValidator.isValid()) { - Contact newContact = new Contact(); - newContact.setName(etName.getText().toString()); - newContact.setEmail(etEmail.getText().toString()); + public void createOrModifyContact(){ + if(contactId >= 0) { + // Modifying existing contact - for (ContactAddress contactAddress : contactAddressList){ - newContact.addAddress(contactAddress); + if (this.modifyContactValidator.isValid()) { + this.contact.setName(tietName.getText().toString()); + this.contact.clearAddresses(); + + for (ContactAddress contactAddress : contactAddressList){ + this.contact.addAddress(contactAddress); + } + + ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); + if (contactViewModel.modifyContact(this.contact)){ + this.finish(); + } else { + this.modifyContactValidator.validate(); + } } + } else { + // Creating a new contact - ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); - if (contactViewModel.addContact(newContact)){ - this.finish(); - } else { - createContactValidator.validate(); + if (this.createContactValidator.isValid()) { + Contact newContact = new Contact(); + newContact.setName(tietName.getText().toString()); + + for (ContactAddress contactAddress : contactAddressList){ + newContact.addAddress(contactAddress); + } + + ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); + if (contactViewModel.addContact(newContact)){ + this.finish(); + } else { + createContactValidator.validate(); + } } } } @@ -211,10 +197,8 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida activity.runOnUiThread(new Runnable() { public void run() { - if (field.getView() == etName) { - tvNameError.setText(""); - } else if (field.getView() == etEmail) { - tvEmailError.setText(""); + if (field.getView() == tietName) { + tilName.setError(""); } if (activity.isValid()){ @@ -232,10 +216,8 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida @Override public void run() { - if (field.getView() == etName) { - tvNameError.setText(field.getMessage()); - } else if (field.getView() == etEmail) { - tvEmailError.setText(field.getMessage()); + if (field.getView() == tietName) { + tilName.setError(field.getMessage()); } } }); diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java index 1b84e43..2c91b83 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java @@ -15,9 +15,8 @@ import cy.agorise.crystalwallet.viewmodels.validators.validationfields.PinValida public class CreateContactValidator extends UIValidator { - public CreateContactValidator(Context context, EditText nameEdit, EditText emailEdit){ + public CreateContactValidator(Context context, EditText nameEdit){ super(context); this.addField(new ContactNameValidationField(nameEdit)); - this.addField(new EmailValidationField(emailEdit)); } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/ModifyContactValidator.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/ModifyContactValidator.java index ec640fd..b629434 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/ModifyContactValidator.java +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/ModifyContactValidator.java @@ -13,9 +13,8 @@ import cy.agorise.crystalwallet.viewmodels.validators.validationfields.EmailVali public class ModifyContactValidator extends UIValidator { - public ModifyContactValidator(Context context, Contact contact, EditText nameEdit, EditText emailEdit){ + public ModifyContactValidator(Context context, Contact contact, EditText nameEdit){ super(context); this.addField(new ContactNameValidationField(nameEdit, contact)); - this.addField(new EmailValidationField(emailEdit)); } } diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml deleted file mode 100644 index 285ab12..0000000 --- a/app/src/main/res/layout/activity_account.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - -