<activity
android:name=".ui.activity.ProfileDetailActivity"
android:label="@string/title_profile_details"
- android:parentActivityName=".ui.activity.ProfileListActivity"
+ android:parentActivityName=".ui.activity.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
--- /dev/null
+/*
+ * Copyright © 2019 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe is free software: you can distribute it and/or modify it
+ * under the term of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your opinion), any later version.
+ *
+ * MoLe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License terms for details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger;
+
+import androidx.lifecycle.ViewModel;
+
+public class ProfileListViewModel extends ViewModel {
+ // TODO: Implement the ViewModel
+}
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.core.view.GravityCompat;
-import androidx.viewpager.widget.ViewPager;
-import androidx.drawerlayout.widget.DrawerLayout;
-import androidx.appcompat.app.ActionBarDrawerToggle;
-import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+
import net.ktnx.mobileledger.R;
import net.ktnx.mobileledger.async.RefreshDescriptionsTask;
import net.ktnx.mobileledger.async.RetrieveTransactionsTask;
import net.ktnx.mobileledger.model.LedgerAccount;
import net.ktnx.mobileledger.model.MobileLedgerProfile;
import net.ktnx.mobileledger.ui.account_summary.AccountSummaryFragment;
+import net.ktnx.mobileledger.ui.profiles.ProfileDetailFragment;
+import net.ktnx.mobileledger.ui.profiles.ProfilesRecyclerViewAdapter;
import net.ktnx.mobileledger.ui.transaction_list.TransactionListFragment;
import net.ktnx.mobileledger.utils.Colors;
import net.ktnx.mobileledger.utils.MLDB;
import java.text.DateFormat;
import java.util.Date;
+import androidx.appcompat.app.ActionBarDrawerToggle;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.view.GravityCompat;
+import androidx.drawerlayout.widget.DrawerLayout;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewpager.widget.ViewPager;
+
public class MainActivity extends CrashReportingActivity {
+ private static final String STATE_CURRENT_PAGE = "current_page";
+ private static final String BUNDLE_SAVED_STATE = "bundle_savedState";
DrawerLayout drawer;
+ private LinearLayout profileListContainer;
+ private View profileListHeadArrow;
private FragmentManager fragmentManager;
private TextView tvLastUpdate;
private RetrieveTransactionsTask retrieveTransactionsTask;
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
private FloatingActionButton fab;
+ private boolean profileModificationEnabled = false;
+ private boolean profileListExpanded = false;
+ private ProfilesRecyclerViewAdapter mProfileListAdapter;
@Override
protected void onStart() {
}
}
@Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_CURRENT_PAGE, mViewPager.getCurrentItem());
+ }
+ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+
+ fab = findViewById(R.id.btn_add_transaction);
+ profileListContainer = findViewById(R.id.nav_profile_list_container);
+ profileListHeadArrow = findViewById(R.id.nav_profiles_arrow);
+ drawer = findViewById(R.id.drawer_layout);
+ tvLastUpdate = findViewById(R.id.transactions_last_update);
+ bTransactionListCancelDownload = findViewById(R.id.transaction_list_cancel_download);
+ progressBar = findViewById(R.id.transaction_list_progress_bar);
+ progressLayout = findViewById(R.id.transaction_progress_layout);
+ fragmentManager = getSupportFragmentManager();
+ mSectionsPagerAdapter = new SectionsPagerAdapter(fragmentManager);
+ mViewPager = findViewById(R.id.root_frame);
+
+ Bundle extra = getIntent().getBundleExtra(BUNDLE_SAVED_STATE);
+ if (extra != null && savedInstanceState == null) savedInstanceState = extra;
+
+
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
- fab = findViewById(R.id.btn_add_transaction);
Data.profile.addObserver((o, arg) -> {
MobileLedgerProfile profile = Data.profile.get();
});
});
- drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle =
new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
e.printStackTrace();
}
- tvLastUpdate = findViewById(R.id.transactions_last_update);
-
- bTransactionListCancelDownload = findViewById(R.id.transaction_list_cancel_download);
- progressBar = findViewById(R.id.transaction_list_progress_bar);
if (progressBar == null)
throw new RuntimeException("Can't get hold on the transaction value progress bar");
- progressLayout = findViewById(R.id.transaction_progress_layout);
if (progressLayout == null) throw new RuntimeException(
"Can't get hold on the transaction value progress bar layout");
- fragmentManager = getSupportFragmentManager();
- mSectionsPagerAdapter = new SectionsPagerAdapter(fragmentManager);
-
markDrawerItemCurrent(R.id.nav_account_summary);
- mViewPager = findViewById(R.id.root_frame);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
}
});
+ if (savedInstanceState != null) {
+ int currentPage = savedInstanceState.getInt(STATE_CURRENT_PAGE, -1);
+ if (currentPage != -1) {
+ mViewPager.setCurrentItem(currentPage, false);
+ }
+ }
+
Data.lastUpdateDate.addObserver((o, arg) -> {
Log.d("main", "lastUpdateDate changed");
runOnUiThread(() -> {
});
});
- findViewById(R.id.btn_no_profiles_add).setOnClickListener(v -> startAddProfileActivity());
+ findViewById(R.id.btn_no_profiles_add)
+ .setOnClickListener(v -> startEditProfileActivity(null));
findViewById(R.id.btn_add_transaction).setOnClickListener(this::fabNewTransactionClicked);
+
+ findViewById(R.id.nav_new_profile_button)
+ .setOnClickListener(v -> startEditProfileActivity(null));
+
+ RecyclerView root = findViewById(R.id.nav_profile_list);
+ if (root == null)
+ throw new RuntimeException("Can't get hold on the transaction value view");
+
+ mProfileListAdapter = new ProfilesRecyclerViewAdapter();
+ root.setAdapter(mProfileListAdapter);
+
+ LinearLayoutManager llm = new LinearLayoutManager(this);
+
+ llm.setOrientation(RecyclerView.VERTICAL);
+ root.setLayoutManager(llm);
}
private void profileThemeChanged() {
setupProfileColors();
+ Bundle bundle = new Bundle();
+ onSaveInstanceState(bundle);
// restart activity to reflect theme change
finish();
Intent intent = new Intent(this, this.getClass());
+ intent.putExtra(BUNDLE_SAVED_STATE, bundle);
startActivity(intent);
}
@Override
super.onResume();
setupProfile();
}
- private void startAddProfileActivity() {
- Intent intent = new Intent(this, ProfileListActivity.class);
+ public void startEditProfileActivity(MobileLedgerProfile profile) {
+ Intent intent = new Intent(this, ProfileDetailActivity.class);
Bundle args = new Bundle();
- args.putInt(ProfileListActivity.ARG_ACTION, ProfileListActivity.ACTION_EDIT_PROFILE);
- args.putInt(ProfileListActivity.ARG_PROFILE_INDEX, ProfileListActivity.PROFILE_INDEX_NONE);
+ if (profile != null) {
+ int index = Data.getProfileIndex(profile);
+ if (index != -1) intent.putExtra(ProfileDetailFragment.ARG_ITEM_ID, index);
+ }
intent.putExtras(args);
startActivity(intent, args);
}
progressBar.setIndeterminate(false);
}
}
- public void navProfilesClicked(View view) {
- drawer.closeDrawers();
- Intent intent = new Intent(this, ProfileListActivity.class);
- startActivity(intent);
- }
public void fabShouldShow() {
MobileLedgerProfile profile = Data.profile.get();
if ((profile != null) && profile.isPostingPermitted()) fab.show();
}
+ public void navProfilesHeadClicked(View view) {
+ if (profileListExpanded) {
+ collapseProfileList();
+ }
+ else {
+ expandProfileList();
+ }
+ }
+ private void expandProfileList() {
+ profileListExpanded = true;
+
+
+ profileListContainer.setVisibility(View.VISIBLE);
+ profileListContainer.startAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_down));
+ profileListHeadArrow.startAnimation(AnimationUtils.loadAnimation(this, R.anim.rotate_180));
+ }
+ private void collapseProfileList() {
+ profileListExpanded = false;
+
+ final Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_up);
+ animation.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ profileListContainer.setVisibility(View.GONE);
+ }
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+ });
+ profileListContainer.startAnimation(animation);
+ profileListHeadArrow
+ .startAnimation(AnimationUtils.loadAnimation(this, R.anim.rotate_180_back));
+
+ mProfileListAdapter.stopEditingProfiles();
+ }
+ public void onProfileRowClicked(View v) {
+ Data.setCurrentProfile((MobileLedgerProfile) v.getTag());
+ }
+ public void enableProfileModifications() {
+ profileModificationEnabled = true;
+ ViewGroup profileList = findViewById(R.id.nav_profile_list);
+ for (int i = 0; i < profileList.getChildCount(); i++) {
+ View aRow = profileList.getChildAt(i);
+ aRow.findViewById(R.id.profile_list_edit_button).setVisibility(View.VISIBLE);
+ aRow.findViewById(R.id.profile_list_rearrange_handle).setVisibility(View.VISIBLE);
+ }
+ // FIXME enable rearranging
+
+ }
+ public void disableProfileModifications() {
+ profileModificationEnabled = false;
+ ViewGroup profileList = findViewById(R.id.nav_profile_list);
+ for (int i = 0; i < profileList.getChildCount(); i++) {
+ View aRow = profileList.getChildAt(i);
+ aRow.findViewById(R.id.profile_list_edit_button).setVisibility(View.GONE);
+ aRow.findViewById(R.id.profile_list_rearrange_handle).setVisibility(View.GONE);
+ }
+ // FIXME disable rearranging
+
+ }
public class SectionsPagerAdapter extends FragmentPagerAdapter {
return 2;
}
}
+
}
package net.ktnx.mobileledger.ui.activity;
-import android.content.Intent;
import android.os.Bundle;
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.android.material.snackbar.Snackbar;
-import androidx.appcompat.app.ActionBar;
-import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
import net.ktnx.mobileledger.R;
import net.ktnx.mobileledger.model.Data;
import net.ktnx.mobileledger.model.MobileLedgerProfile;
import net.ktnx.mobileledger.ui.profiles.ProfileDetailFragment;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.widget.Toolbar;
+
/**
* An activity representing a single Profile detail screen. This
* activity is only used on narrow width devices. On tablet-size devices,
return true;
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
- if (id == android.R.id.home) {
- // This ID represents the Home or Up button. In the case of this
- // activity, the Up button is shown. For
- // more details, see the Navigation pattern on Android Design:
- //
- // http://developer.android.com/design/patterns/navigation.html#up-vs-back
- //
- navigateUpTo(new Intent(this, ProfileListActivity.class));
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
}
+++ /dev/null
-/*
- * Copyright © 2019 Damyan Ivanov.
- * This file is part of MoLe.
- * MoLe is free software: you can distribute it and/or modify it
- * under the term of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your opinion), any later version.
- *
- * MoLe is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License terms for details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package net.ktnx.mobileledger.ui.activity;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.ActionBar;
-import androidx.recyclerview.widget.DividerItemDecoration;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.appcompat.widget.Toolbar;
-import androidx.recyclerview.widget.ItemTouchHelper;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RadioButton;
-import android.widget.TextView;
-
-import net.ktnx.mobileledger.R;
-import net.ktnx.mobileledger.model.Data;
-import net.ktnx.mobileledger.model.MobileLedgerProfile;
-import net.ktnx.mobileledger.ui.profiles.ProfileDetailFragment;
-import net.ktnx.mobileledger.utils.Colors;
-
-import java.util.Collections;
-
-/**
- * An activity representing a list of Profiles. This activity
- * has different presentations for handset and tablet-size devices. On
- * handsets, the activity presents a list of items, which when touched,
- * lead to a {@link ProfileDetailActivity} representing
- * item details. On tablets, the activity presents the list of items and
- * item details side-by-side using two vertical panes.
- */
-public class ProfileListActivity extends CrashReportingActivity {
-
- public static final String ARG_ACTION = "action";
- public static final String ARG_PROFILE_INDEX = "profile_index";
- public static final int PROFILE_INDEX_NONE = -1;
- public static final int ACTION_EDIT_PROFILE = 1;
- public static final int ACTION_INVALID = -1;
- /**
- * Whether or not the activity is in two-pane mode, i.e. running on a tablet
- * device.
- */
- private boolean mTwoPane;
- private RecyclerView recyclerView;
-
- @Override
- public boolean onSupportNavigateUp() {
- onBackPressed();
- return super.onSupportNavigateUp();
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_profile_list);
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- toolbar.setTitle(getTitle());
- final ActionBar supportActionBar = getSupportActionBar();
- if (supportActionBar != null) {
- supportActionBar.setDisplayHomeAsUpEnabled(true);
- supportActionBar.setDisplayShowHomeEnabled(true);
- }
-
- recyclerView = findViewById(R.id.profile_list);
- if (recyclerView == null) throw new AssertionError();
- setupRecyclerView(recyclerView);
-
- if (findViewById(R.id.profile_detail_container) != null) {
- // The detail container view will be present only in the
- // large-screen layouts (res/values-w900dp).
- // If this view is present, then the
- // activity should be in two-pane mode.
- mTwoPane = true;
- }
-
- int action = getIntent().getIntExtra(ARG_ACTION, ACTION_INVALID);
- if (action == ACTION_EDIT_PROFILE) {
- Log.d("profiles", "got edit profile action");
- int index = getIntent().getIntExtra(ARG_PROFILE_INDEX, PROFILE_INDEX_NONE);
-
- MobileLedgerProfile profile = (index >= 0) ? Data.profiles.get(index) : null;
- ProfilesRecyclerViewAdapter adapter =
- (ProfilesRecyclerViewAdapter) recyclerView.getAdapter();
- if (adapter != null) {
- adapter.editProfile(recyclerView, profile);
-
- // if invoked from the initial screen, get out so that when the new profile
- // activity finishes the user i navigated to the main activity
- if ((profile == null) && Data.profiles.getList().isEmpty()) finish();
- }
- }
- }
- void launchNewProfileActivity() {
- ProfilesRecyclerViewAdapter adapter =
- (ProfilesRecyclerViewAdapter) recyclerView.getAdapter();
- if (adapter != null) adapter.editProfile(recyclerView, null);
- }
- private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
- final ProfilesRecyclerViewAdapter adapter = new ProfilesRecyclerViewAdapter(this, mTwoPane);
- recyclerView.setAdapter(adapter);
- ItemTouchHelper.Callback cb = new ItemTouchHelper.Callback() {
- @Override
- public int getMovementFlags(@NonNull RecyclerView recyclerView,
- @NonNull RecyclerView.ViewHolder viewHolder) {
- return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0);
- }
- @Override
- public boolean onMove(@NonNull RecyclerView recyclerView,
- @NonNull RecyclerView.ViewHolder viewHolder,
- @NonNull RecyclerView.ViewHolder target) {
- Collections.swap(Data.profiles.getList(), viewHolder.getAdapterPosition(),
- target.getAdapterPosition());
- MobileLedgerProfile.storeProfilesOrder();
- adapter.notifyItemMoved(viewHolder.getAdapterPosition(),
- target.getAdapterPosition());
- return true;
- }
- @Override
- public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
-
- }
- };
- new ItemTouchHelper(cb).attachToRecyclerView(recyclerView);
- recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(),
- DividerItemDecoration.VERTICAL));
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.profile_list, menu);
- menu.findItem(R.id.menu_add_profile).setOnMenuItemClickListener(item -> {
- launchNewProfileActivity();
- return true;
- });
- return super.onCreateOptionsMenu(menu);
- }
- public static class ProfilesRecyclerViewAdapter
- extends RecyclerView.Adapter<ProfilesRecyclerViewAdapter.ProfileListViewHolder> {
-
- private final ProfileListActivity mParentActivity;
- private final boolean mTwoPane;
- private final View.OnClickListener mOnClickListener = view -> {
- MobileLedgerProfile profile = (MobileLedgerProfile) ((View) view.getParent()).getTag();
- editProfile(view, profile);
- };
- ProfilesRecyclerViewAdapter(ProfileListActivity parent, boolean twoPane) {
- mParentActivity = parent;
- mTwoPane = twoPane;
- Data.profiles.addObserver((o, arg) -> {
- Log.d("profiles", "profile list changed");
- if (arg == null) notifyDataSetChanged();
- else notifyItemChanged((int) arg);
- });
- }
- private void editProfile(View view, MobileLedgerProfile profile) {
- int index = Data.profiles.indexOf(profile);
- if (mTwoPane) {
- Bundle arguments = new Bundle();
- arguments.putInt(ProfileDetailFragment.ARG_ITEM_ID, index);
- ProfileDetailFragment fragment = new ProfileDetailFragment();
- fragment.setArguments(arguments);
- mParentActivity.getSupportFragmentManager().beginTransaction()
- .replace(R.id.profile_detail_container, fragment).commit();
- }
- else {
- Context context = view.getContext();
- Intent intent = new Intent(context, ProfileDetailActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
- if (index != -1) intent.putExtra(ProfileDetailFragment.ARG_ITEM_ID, index);
-
- context.startActivity(intent);
- }
- }
- @NonNull
- @Override
- public ProfileListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.profile_list_content, parent, false);
- ProfileListViewHolder holder = new ProfileListViewHolder(view);
-
- holder.mRadioView.setOnCheckedChangeListener((buttonView, isChecked) -> {
- if (!isChecked) return;
- Log.d("profiles",
- String.format("Item %d got checked", holder.getAdapterPosition()));
- MobileLedgerProfile profile = (MobileLedgerProfile) holder.itemView.getTag();
- if (profile != null) {
- Log.d("profiles",
- String.format("Setting current profile to %s", profile.getUuid()));
- Data.setCurrentProfile(profile);
- }
- });
- View.OnClickListener profileSelector = v -> holder.mRadioView.setChecked(true);
- holder.mTitle.setOnClickListener(profileSelector);
- holder.mSubTitle.setOnClickListener(profileSelector);
- Data.profile.addObserver((o, arg) -> {
- MobileLedgerProfile myProfile = (MobileLedgerProfile) holder.itemView.getTag();
- final MobileLedgerProfile currentProfile = Data.profile.get();
- final boolean sameProfile = currentProfile.equals(myProfile);
- if (holder.mRadioView.isChecked() != sameProfile) {
- holder.mRadioView.setChecked(sameProfile);
- }
- });
- return holder;
- }
- @Override
- public void onBindViewHolder(@NonNull final ProfileListViewHolder holder, int position) {
- final MobileLedgerProfile profile = Data.profiles.get(position);
- final MobileLedgerProfile currentProfile = Data.profile.get();
- Log.d("profiles", String.format("pos %d: %s, current: %s", position, profile.getUuid(),
- (currentProfile == null) ? "<NULL>" : currentProfile.getUuid()));
- holder.itemView.setTag(profile);
-
- int hue = profile.getThemeId();
- if (hue == -1) holder.mColorTag.setBackgroundColor(Color.TRANSPARENT);
- else holder.mColorTag.setBackgroundColor(Colors.getPrimaryColorForHue(hue));
-
- holder.mTitle.setText(profile.getName());
- holder.mSubTitle.setText(profile.getUrl());
- holder.mRadioView.setChecked(profile.equals(currentProfile));
-
- holder.mEditButton.setOnClickListener(mOnClickListener);
- }
- @Override
- public int getItemCount() {
- return Data.profiles.size();
- }
- class ProfileListViewHolder extends RecyclerView.ViewHolder {
- final RadioButton mRadioView;
- final TextView mEditButton;
- final TextView mTitle, mSubTitle, mColorTag;
-
- ProfileListViewHolder(View view) {
- super(view);
- mRadioView = view.findViewById(R.id.profile_list_radio);
- mEditButton = view.findViewById(R.id.profile_list_edit_button);
- mTitle = view.findViewById(R.id.title);
- mSubTitle = view.findViewById(R.id.subtitle);
- mColorTag = view.findViewById(R.id.colorTag);
- }
- }
- }
-}
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.android.material.textfield.TextInputLayout;
-import androidx.fragment.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.Switch;
import android.widget.TextView;
+import com.google.android.material.appbar.CollapsingToolbarLayout;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.textfield.TextInputLayout;
+
import net.ktnx.mobileledger.R;
import net.ktnx.mobileledger.model.Data;
import net.ktnx.mobileledger.model.MobileLedgerProfile;
import net.ktnx.mobileledger.ui.activity.ProfileDetailActivity;
-import net.ktnx.mobileledger.ui.activity.ProfileListActivity;
import net.ktnx.mobileledger.utils.Colors;
import org.jetbrains.annotations.NotNull;
import java.util.List;
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
/**
* A fragment representing a single Profile detail screen.
- * This fragment is either contained in a {@link ProfileListActivity}
- * in two-pane mode (on tablets) or a {@link ProfileDetailActivity}
+ * a {@link ProfileDetailActivity}
* on handsets.
*/
public class ProfileDetailFragment extends Fragment {
--- /dev/null
+/*
+ * Copyright © 2019 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe is free software: you can distribute it and/or modify it
+ * under the term of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your opinion), any later version.
+ *
+ * MoLe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License terms for details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.ui.profiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import net.ktnx.mobileledger.R;
+import net.ktnx.mobileledger.model.Data;
+import net.ktnx.mobileledger.model.MobileLedgerProfile;
+import net.ktnx.mobileledger.ui.activity.ProfileDetailActivity;
+import net.ktnx.mobileledger.utils.Colors;
+
+import java.util.Collections;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.RecyclerView;
+
+public class ProfilesRecyclerViewAdapter
+ extends RecyclerView.Adapter<ProfilesRecyclerViewAdapter.ProfileListViewHolder> {
+ private final View.OnClickListener mOnClickListener = view -> {
+ MobileLedgerProfile profile = (MobileLedgerProfile) ((View) view.getParent()).getTag();
+ editProfile(view, profile);
+ };
+ private boolean editingProfiles = false;
+ private RecyclerView recyclerView;
+ private ItemTouchHelper rearrangeHelper;
+ public ProfilesRecyclerViewAdapter() {
+ Data.profiles.addObserver((o, arg) -> {
+ Log.d("profiles", "profile list changed");
+ if (arg == null) notifyDataSetChanged();
+ else notifyItemChanged((int) arg);
+ });
+
+ ItemTouchHelper.Callback cb = new ItemTouchHelper.Callback() {
+ @Override
+ public int getMovementFlags(@NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder) {
+ return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0);
+ }
+ @Override
+ public boolean onMove(@NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder,
+ @NonNull RecyclerView.ViewHolder target) {
+ Collections.swap(Data.profiles.getList(), viewHolder.getAdapterPosition(),
+ target.getAdapterPosition());
+ MobileLedgerProfile.storeProfilesOrder();
+ notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
+ return true;
+ }
+ @Override
+ public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
+ }
+ };
+ rearrangeHelper = new ItemTouchHelper(cb);
+ }
+ @Override
+ public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
+ rearrangeHelper.attachToRecyclerView(null);
+ super.onDetachedFromRecyclerView(recyclerView);
+ this.recyclerView = null;
+ }
+ @Override
+ public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
+ super.onAttachedToRecyclerView(recyclerView);
+ this.recyclerView = recyclerView;
+ rearrangeHelper.attachToRecyclerView(recyclerView);
+ }
+ public boolean editingProfiles() {
+ return this.editingProfiles;
+ }
+ public void startEditingProfiles() {
+ if (editingProfiles) return;
+ this.editingProfiles = true;
+ notifyDataSetChanged();
+ rearrangeHelper.attachToRecyclerView(recyclerView);
+ }
+ public void stopEditingProfiles() {
+ if (!editingProfiles) return;
+ this.editingProfiles = false;
+ notifyDataSetChanged();
+ rearrangeHelper.attachToRecyclerView(null);
+ }
+ public void flipEditingProfiles() {
+ if (editingProfiles) stopEditingProfiles();
+ else startEditingProfiles();
+ }
+ private void editProfile(View view, MobileLedgerProfile profile) {
+ int index = Data.profiles.indexOf(profile);
+ Context context = view.getContext();
+ Intent intent = new Intent(context, ProfileDetailActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
+ if (index != -1) intent.putExtra(ProfileDetailFragment.ARG_ITEM_ID, index);
+
+ context.startActivity(intent);
+ }
+ @NonNull
+ @Override
+ public ProfileListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.profile_list_content, parent, false);
+ ProfileListViewHolder holder = new ProfileListViewHolder(view);
+
+ holder.mTitle.setOnClickListener(v -> {
+ View row = (View) v.getParent();
+ MobileLedgerProfile profile = (MobileLedgerProfile) row.getTag();
+ if (profile == null)
+ throw new IllegalStateException("Profile row without associated profile");
+ Log.d("profiles", "Setting profile to " + profile.getName());
+ Data.setCurrentProfile(profile);
+ });
+ holder.mTitle.setOnLongClickListener(v -> {
+ flipEditingProfiles();
+ return true;
+ });
+ Data.profile.addObserver((o, arg) -> {
+ MobileLedgerProfile myProfile = (MobileLedgerProfile) holder.itemView.getTag();
+ final MobileLedgerProfile currentProfile = Data.profile.get();
+ final boolean sameProfile = currentProfile.equals(myProfile);
+ view.setAlpha(sameProfile ? 1 : 0.5f);
+ });
+ return holder;
+ }
+ @Override
+ public void onBindViewHolder(@NonNull final ProfileListViewHolder holder, int position) {
+ final MobileLedgerProfile profile = Data.profiles.get(position);
+ final MobileLedgerProfile currentProfile = Data.profile.get();
+ Log.d("profiles", String.format("pos %d: %s, current: %s", position, profile.getUuid(),
+ (currentProfile == null) ? "<NULL>" : currentProfile.getUuid()));
+ holder.itemView.setTag(profile);
+
+ int hue = profile.getThemeId();
+ if (hue == -1) holder.mColorTag.setBackgroundColor(Color.TRANSPARENT);
+ else holder.mColorTag.setBackgroundColor(Colors.getPrimaryColorForHue(hue));
+
+ holder.mTitle.setText(profile.getName());
+// holder.mSubTitle.setText(profile.getUrl());
+
+ holder.mEditButton.setOnClickListener(mOnClickListener);
+
+ final boolean sameProfile = currentProfile.equals(profile);
+ holder.itemView.setAlpha(sameProfile ? 1 : 0.5f);
+ holder.itemView
+ .setBackground(sameProfile ? new ColorDrawable(Colors.tableRowLightBG) : null);
+ if (editingProfiles) {
+ holder.mRearrangeHandle.setVisibility(View.VISIBLE);
+ holder.mEditButton.setVisibility(View.VISIBLE);
+ }
+ else {
+ holder.mRearrangeHandle.setVisibility(View.GONE);
+ holder.mEditButton.setVisibility(View.GONE);
+ }
+ }
+ @Override
+ public int getItemCount() {
+ return Data.profiles.size();
+ }
+ class ProfileListViewHolder extends RecyclerView.ViewHolder {
+ final TextView mEditButton;
+ final TextView mTitle, mColorTag;
+ final ImageView mRearrangeHandle;
+
+ ProfileListViewHolder(View view) {
+ super(view);
+ mEditButton = view.findViewById(R.id.profile_list_edit_button);
+ mTitle = view.findViewById(R.id.title);
+ mColorTag = view.findViewById(R.id.colorTag);
+ mRearrangeHandle = view.findViewById(R.id.profile_list_rearrange_handle);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2019 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe is free software: you can distribute it and/or modify it
+ * under the term of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your opinion), any later version.
+ *
+ * MoLe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License terms for details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.ui.profiles.dummy;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class for providing sample content for user interfaces created by
+ * Android template wizards.
+ * <p>
+ * TODO: Replace all uses of this class before publishing your app.
+ */
+public class DummyContent {
+
+ /**
+ * An array of sample (dummy) items.
+ */
+ public static final List<DummyItem> ITEMS = new ArrayList<DummyItem>();
+
+ /**
+ * A map of sample (dummy) items, by ID.
+ */
+ public static final Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
+
+ private static final int COUNT = 25;
+
+ static {
+ // Add some sample items.
+ for (int i = 1; i <= COUNT; i++) {
+ addItem(createDummyItem(i));
+ }
+ }
+
+ private static void addItem(DummyItem item) {
+ ITEMS.add(item);
+ ITEM_MAP.put(item.id, item);
+ }
+
+ private static DummyItem createDummyItem(int position) {
+ return new DummyItem(String.valueOf(position), "Item " + position, makeDetails(position));
+ }
+
+ private static String makeDetails(int position) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Details about Item: ").append(position);
+ for (int i = 0; i < position; i++) {
+ builder.append("\nMore details information here.");
+ }
+ return builder.toString();
+ }
+
+ /**
+ * A dummy item representing a piece of content.
+ */
+ public static class DummyItem {
+ public final String id;
+ public final String content;
+ public final String details;
+
+ public DummyItem(String id, String content, String details) {
+ this.id = id;
+ this.content = content;
+ this.details = details;
+ }
+
+ @Override
+ public String toString() {
+ return content;
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:animation="@anim/slide_in_right"
+ android:interpolator="@android:anim/accelerate_decelerate_interpolator" />
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:fillAfter="true">
+ <rotate
+ android:fromDegrees="0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toDegrees="180" />
+</set>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:fillAfter="true">
+ <rotate
+ android:fromDegrees="180"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toDegrees="0" />
+</set>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:fillAfter="true"
+ android:fillEnabled="true">
+ <scale
+ android:fillAfter="false"
+ android:fromYScale="0.0"
+ android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+ android:toYScale="1.0"
+ android:fromXScale="1.0"
+ android:toXScale="1.0"/>
+</set>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="@android:integer/config_shortAnimTime">
+ <translate
+ android:fromYDelta="-100%"
+ android:toYDelta="0%" />
+</set>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:fillAfter="true"
+ android:fillEnabled="true">
+ <scale
+ android:fillAfter="false"
+ android:fromYScale="1.0"
+ android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+ android:toYScale="0.0"
+ android:fromXScale="1.0"
+ android:toXScale="1.0"/>
+</set>
\ No newline at end of file
--- /dev/null
+<!--
+ ~ Copyright Google Inc.
+ ~
+ ~ 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:
+ ~
+ ~ https://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distribution 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.
+ -->
+
+<vector android:height="24dp" android:tint="?colorAccent"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6z"/>
+</vector>
--- /dev/null
+<!--
+ ~ Copyright Google Inc.
+ ~
+ ~ 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:
+ ~
+ ~ https://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distribution 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.
+ -->
+
+<vector android:height="24dp" android:tint="?colorPrimary"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M7.41,7.84L12,12.42l4.59,-4.58L18,9.25l-6,6 -6,-6z"/>
+</vector>
--- /dev/null
+<!--
+ ~ Copyright Google Inc.
+ ~
+ ~ 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:
+ ~
+ ~ https://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distribution 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.
+ -->
+
+<vector android:height="24dp" android:tint="?colorAccent"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M12,5.83L15.17,9l1.41,-1.41L12,3 7.41,7.59 8.83,9 12,5.83zM12,18.17L8.83,15l-1.41,1.41L12,21l4.59,-4.59L15.17,15 12,18.17z"/>
+</vector>
<include layout="@layout/no_profiles" />
</androidx.constraintlayout.widget.ConstraintLayout>
- <com.google.android.material.navigation.NavigationView
- android:id="@+id/nav_view"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="start"
- android:fitsSystemWindows="true"
- android:theme="@style/ThemeOverlay.AppCompat.Light">
-
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginBottom="0dp"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/nav_fixed_items"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:divider="@drawable/list_divider"
- android:elevation="2dp"
- android:orientation="vertical"
- android:showDividers="beginning"
- app:layout_constraintBottom_toBottomOf="parent">
-
- <TextView
- android:id="@+id/nav_profiles"
- style="@style/nav_button"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:drawableStart="@drawable/ic_view_list_black_24dp"
- android:onClick="navProfilesClicked"
- android:text="@string/profiles" />
-
- <TextView
- android:id="@+id/textView2"
- style="@style/nav_button"
- android:layout_weight="1"
- android:drawableStart="@drawable/ic_settings_black_24dp"
- android:onClick="navSettingsClicked"
- android:text="@string/action_settings" />
-
- </LinearLayout>
-
- <ScrollView
- android:layout_width="0dp"
- android:layout_height="0dp"
- app:layout_constraintBottom_toTopOf="@+id/nav_fixed_items"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent">
-
- <LinearLayout
- android:id="@+id/nav_upper"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:divider="@drawable/list_divider_inside_out"
- android:orientation="vertical"
- android:showDividers="beginning"
- app:layout_constraintBottom_toTopOf="@+id/nav_fixed_items"
- app:layout_constraintTop_toBottomOf="@+id/nav_header">
-
- <LinearLayout
- android:id="@+id/nav_header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/side_nav_bar"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:padding="@dimen/activity_vertical_margin"
- android:theme="@style/ThemeOverlay.AppCompat.Dark"
- app:layout_constraintTop_toTopOf="parent">
-
- <include layout="@layout/nav_header_logo" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/activity_horizontal_margin"
- android:layout_marginEnd="@dimen/activity_horizontal_margin"
- android:gravity="center_vertical"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/app_name"
- android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
-
- <TextView
- android:id="@+id/drawer_version_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="dummy version"
- tools:ignore="HardcodedText" />
- </LinearLayout>
-
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/nav_actions"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/nav_account_summary"
- style="@style/nav_button"
- android:drawableStart="@drawable/ic_home_black_24dp"
- android:onClick="onAccountSummaryClicked"
- android:text="@string/account_summary_title" />
-
- <TextView
- android:id="@+id/nav_latest_transactions"
- style="@style/nav_button"
- android:drawableStart="@drawable/ic_event_note_black_24dp"
- android:onClick="onLatestTransactionsClicked"
- android:text="@string/nav_latest_transactions_title" />
-
- <TextView
- android:id="@+id/textView5"
- style="@style/nav_button"
- android:drawableStart="@drawable/ic_assignment_black_24dp"
- android:text="@string/nav_reports_title" />
-
- </LinearLayout>
-
- </LinearLayout>
- </ScrollView>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- </com.google.android.material.navigation.NavigationView>
+ <include layout="@layout/main_navigation" />
</androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<com.google.android.material.navigation.NavigationView 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/nav_view"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:fitsSystemWindows="true"
+ android:theme="@style/ThemeOverlay.AppCompat.Light"
+ tools:showIn="@layout/activity_main">
+
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="0dp"
+ android:animateLayoutChanges="true"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/nav_fixed_items"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:divider="@drawable/list_divider"
+ android:elevation="2dp"
+ android:orientation="vertical"
+ android:showDividers="beginning"
+ app:layout_constraintBottom_toBottomOf="parent">
+
+ <TextView
+ android:id="@+id/textView2"
+ style="@style/nav_button"
+ android:layout_weight="1"
+ android:drawableStart="@drawable/ic_settings_black_24dp"
+ android:onClick="navSettingsClicked"
+ android:text="@string/action_settings" />
+
+ </LinearLayout>
+
+ <ScrollView
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ app:layout_constraintBottom_toTopOf="@+id/nav_fixed_items"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
+
+ <LinearLayout
+ android:id="@+id/nav_upper"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:animateLayoutChanges="true"
+ android:divider="@drawable/list_divider_inside_out"
+ android:orientation="vertical"
+ android:showDividers="beginning"
+ app:layout_constraintBottom_toTopOf="@+id/nav_fixed_items"
+ app:layout_constraintTop_toBottomOf="@+id/nav_header">
+
+ <LinearLayout
+ android:id="@+id/nav_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/side_nav_bar"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:padding="@dimen/activity_vertical_margin"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark"
+ app:layout_constraintTop_toTopOf="parent">
+
+ <include layout="@layout/nav_header_logo" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/activity_horizontal_margin"
+ android:layout_marginEnd="@dimen/activity_horizontal_margin"
+ android:gravity="center_vertical"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/app_name"
+ android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
+
+ <TextView
+ android:id="@+id/drawer_version_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="dummy version"
+ tools:ignore="HardcodedText" />
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/nav_actions"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/nav_account_summary"
+ style="@style/nav_button"
+ android:drawableStart="@drawable/ic_home_black_24dp"
+ android:onClick="onAccountSummaryClicked"
+ android:text="@string/account_summary_title" />
+
+ <TextView
+ android:id="@+id/nav_latest_transactions"
+ style="@style/nav_button"
+ android:drawableStart="@drawable/ic_event_note_black_24dp"
+ android:onClick="onLatestTransactionsClicked"
+ android:text="@string/nav_latest_transactions_title" />
+
+ <TextView
+ android:id="@+id/textView5"
+ style="@style/nav_button"
+ android:drawableStart="@drawable/ic_assignment_black_24dp"
+ android:text="@string/nav_reports_title" />
+
+ <include layout="@layout/nav_profile_list_head" />
+
+ <LinearLayout
+ android:id="@+id/nav_profile_list_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:animateLayoutChanges="true"
+ android:orientation="vertical"
+ android:visibility="gone">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/nav_profile_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingStart="0dp">
+
+ </androidx.recyclerview.widget.RecyclerView>
+
+ <include layout="@layout/nav_profile_list_new_profile_row" />
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+ </ScrollView>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+</com.google.android.material.navigation.NavigationView>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/thumb_row_height"
+ android:paddingEnd="@dimen/activity_horizontal_margin">
+
+ <TextView
+ android:id="@+id/nav_profiles_arrow"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableStart="@drawable/ic_expand_more_black_24dp"
+ android:gravity="end|center_vertical"
+ android:onClick="navProfilesHeadClicked"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <TextView
+ android:id="@+id/nav_profiles_label"
+ style="@style/nav_button"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_marginEnd="8dp"
+ android:drawableStart="@drawable/ic_view_list_black_24dp"
+ android:gravity="start|center_vertical"
+ android:text="@string/profiles"
+ android:onClick="navProfilesHeadClicked"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/nav_profiles_arrow"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright © 2019 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ MoLe is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <androidx.appcompat.widget.AppCompatTextView
+ android:id="@+id/nav_new_profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/thumb_row_height"
+ android:drawableStart="@drawable/ic_add_circle_white_24dp"
+ android:gravity="center_horizontal|center_vertical"
+ android:paddingStart="@dimen/activity_horizontal_margin"
+ android:paddingEnd="@dimen/activity_horizontal_margin"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/profile_list_item"
+ android:alpha="0.50"
+ android:animateLayoutChanges="true"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/thumb_row_height"
android:layout_gravity="center_horizontal"
android:foregroundGravity="center_vertical">
<TextView
android:id="@+id/colorTag"
- android:layout_width="@dimen/activity_horizontal_margin"
+ android:layout_width="16dp"
android:layout_height="0dp"
+ android:layout_marginStart="32dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
android:background="?colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:id="@+id/profile_list_edit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="16dp"
+ android:layout_marginEnd="8dp"
android:layout_weight="9"
android:drawableStart="@drawable/ic_mode_edit_black_24dp"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
+ app:layout_constraintTop_toTopOf="parent"
+ android:visibility="invisible"/>
- <RadioButton
- android:id="@+id/profile_list_radio"
+ <ImageView
+ android:id="@+id/profile_list_rearrange_handle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
android:layout_weight="9"
+ android:background="@drawable/ic_unfold_more_black_24dp"
+ android:visibility="gone"
+ android:layout_marginStart="@dimen/activity_horizontal_margin"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
- tools:ignore="HardcodedText" />
+ app:layout_constraintStart_toEndOf="@id/colorTag"
+ app:layout_constraintEnd_toStartOf="@id/title"/>
<TextView
android:id="@+id/title"
- style="@style/TextAppearance.AppCompat.Large"
+ style="@style/TextAppearance.AppCompat.Medium"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginTop="@dimen/nav_header_vertical_spacing"
- android:layout_marginEnd="16dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:gravity="center_vertical"
+ android:paddingStart="@dimen/activity_horizontal_margin"
android:text="Profile name"
+ app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/profile_list_edit_button"
- app:layout_constraintStart_toEndOf="@id/profile_list_radio"
+ app:layout_constraintStart_toEndOf="@id/profile_list_rearrange_handle"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
- <TextView
- android:id="@+id/subtitle"
- style="@style/TextAppearance.AppCompat.Medium"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- android:layout_marginBottom="@dimen/nav_header_vertical_spacing"
- android:text="Sub-heading"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@id/profile_list_edit_button"
- app:layout_constraintStart_toEndOf="@id/profile_list_radio"
- app:layout_constraintTop_toBottomOf="@id/title"
- tools:ignore="HardcodedText" />
+ <!--<TextView-->
+ <!--android:id="@+id/subtitle"-->
+ <!--style="@style/TextAppearance.AppCompat.Small"-->
+ <!--android:layout_width="0dp"-->
+ <!--android:layout_height="wrap_content"-->
+ <!--android:layout_marginStart="8dp"-->
+ <!--android:layout_marginEnd="8dp"-->
+ <!--android:layout_marginBottom="4dp"-->
+ <!--android:text="Sub-heading"-->
+ <!--app:layout_constraintBottom_toBottomOf="parent"-->
+ <!--app:layout_constraintEnd_toStartOf="@id/profile_list_edit_button"-->
+ <!--app:layout_constraintStart_toEndOf="@id/profile_list_radio"-->
+ <!--app:layout_constraintTop_toBottomOf="@id/title"-->
+ <!--tools:ignore="HardcodedText" />-->
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<resources>
- <style name="nav_button">
+ <style name="nav_button" parent="Base.TextAppearance.AppCompat.Medium">
<item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">48dp</item>
+ <item name="android:layout_height">56dp</item>
<item name="android:clickable">true</item>
- <item name="android:drawablePadding">36dp</item>
+ <item name="android:drawablePadding">@dimen/activity_horizontal_margin</item>
<item name="android:focusable">auto</item>
<item name="android:gravity">center_vertical|start</item>
<item name="android:paddingStart">@dimen/activity_horizontal_margin</item>
<item name="android:paddingEnd">@dimen/activity_horizontal_margin</item>
+ <!--<item name="android:textSize">16sp</item>-->
</style>
</resources>
\ No newline at end of file
<style name="nav_button">
<item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">40dp</item>
+ <item name="android:layout_height">@dimen/thumb_row_height</item>
+ <item name="android:drawablePadding">@dimen/activity_horizontal_margin</item>
<item name="android:clickable">true</item>
- <item name="android:drawablePadding">24dp</item>
<item name="android:focusable">auto</item>
<item name="android:gravity">center_vertical|start</item>
<item name="android:paddingStart">@dimen/activity_horizontal_margin</item>
<item name="android:layout_height">match_parent</item>
</style>
+ <dimen name="thumb_row_height">40dp</dimen>
</resources>