Add view pager for feed and folder management. Put feed management in a fragment

This commit is contained in:
Shinokuni 2019-07-13 13:13:12 +02:00
parent ef8176b324
commit b05fbbe080
11 changed files with 299 additions and 79 deletions

View File

@ -36,6 +36,7 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

View File

@ -33,9 +33,10 @@
android:name=".activities.AddAccountActivity" android:name=".activities.AddAccountActivity"
android:label="@string/add_account" /> android:label="@string/add_account" />
<activity <activity
android:name=".activities.ManageFeedsActivity" android:name=".activities.ManageFeedsFoldersActivity"
android:label="@string/manage_feeds_folders" android:label="@string/manage_feeds_folders"
android:parentActivityName=".activities.MainActivity" /> android:parentActivityName=".activities.MainActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity <activity
android:name=".activities.MainActivity" android:name=".activities.MainActivity"
android:label="@string/articles" android:label="@string/articles"

View File

@ -27,8 +27,8 @@ public class AccountSettingsActivity extends AppCompatActivity {
setTitle(account.getAccountName()); setTitle(account.getAccountName());
binding.accountSettingsFeeds.setOnClickListener(v -> { binding.accountSettingsFeeds.setOnClickListener(v -> {
Intent intent = new Intent(getApplication(), ManageFeedsActivity.class); Intent intent = new Intent(getApplication(), ManageFeedsFoldersActivity.class);
intent.putExtra(ManageFeedsActivity.ACCOUNT, account); intent.putExtra(ManageFeedsFoldersActivity.ACCOUNT, account);
startActivity(intent); startActivity(intent);
}); });

View File

@ -0,0 +1,113 @@
package com.readrops.app.activities;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.readrops.app.R;
import com.readrops.app.database.entities.Account;
import com.readrops.app.databinding.ActivityManageFeedsFoldersBinding;
import com.readrops.app.fragments.FeedsFragment;
import com.readrops.app.fragments.FoldersFragment;
public class ManageFeedsFoldersActivity extends AppCompatActivity {
public static final String ACCOUNT = "ACCOUNT";
private ActivityManageFeedsFoldersBinding binding;
private FeedsFoldersPageAdapter pageAdapter;
private Account account;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_manage_feeds_folders);
setSupportActionBar(binding.manageFeedsFoldersToolbar);
account = getIntent().getParcelableExtra(ACCOUNT);
pageAdapter = new FeedsFoldersPageAdapter(getSupportFragmentManager());
binding.manageFeedsFoldersViewpager.setAdapter(pageAdapter);
binding.manageFeedsFoldersTablayout.setupWithViewPager(binding.manageFeedsFoldersViewpager);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.feeds_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.add_folder:
//addFolder();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
finish();
super.onBackPressed();
}
public class FeedsFoldersPageAdapter extends FragmentPagerAdapter {
private FeedsFoldersPageAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public int getCount() {
return 2;
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getApplicationContext().getString(R.string.feeds_and_folders);
case 1:
return getApplicationContext().getString(R.string.folder);
default:
return null;
}
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = FeedsFragment.newInstance(account);
break;
case 1:
fragment = FoldersFragment.newInstance(account);
break;
}
return fragment;
}
}
}

View File

@ -1,15 +1,19 @@
package com.readrops.app.activities; package com.readrops.app.fragments;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Vibrator; import android.os.Vibrator;
import android.view.Menu; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProviders; import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
@ -18,9 +22,11 @@ import androidx.recyclerview.widget.RecyclerView;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.readrops.app.R; import com.readrops.app.R;
import com.readrops.app.activities.AccountSettingsActivity;
import com.readrops.app.database.entities.Account; import com.readrops.app.database.entities.Account;
import com.readrops.app.database.entities.Folder; import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.pojo.FeedWithFolder; import com.readrops.app.database.pojo.FeedWithFolder;
import com.readrops.app.databinding.FragmentFeedsBinding;
import com.readrops.app.viewmodels.ManageFeedsViewModel; import com.readrops.app.viewmodels.ManageFeedsViewModel;
import com.readrops.app.views.EditFeedDialog; import com.readrops.app.views.EditFeedDialog;
import com.readrops.app.views.FeedsAdapter; import com.readrops.app.views.FeedsAdapter;
@ -29,29 +35,58 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableCompletableObserver; import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
public class ManageFeedsActivity extends AppCompatActivity { import static android.content.Context.VIBRATOR_SERVICE;
import static com.readrops.app.activities.ManageFeedsFoldersActivity.ACCOUNT;
public static final String ACCOUNT = "ACCOUNT";
private RecyclerView recyclerView; public class FeedsFragment extends Fragment {
private FeedsAdapter adapter; private FeedsAdapter adapter;
private ManageFeedsViewModel viewModel; private ManageFeedsViewModel viewModel;
private Account account; private Account account;
@Override private FragmentFeedsBinding binding;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_feeds);
account = getIntent().getParcelableExtra(ACCOUNT); public FeedsFragment() {
// Required empty public constructor
}
public static FeedsFragment newInstance(Account account) {
FeedsFragment fragment = new FeedsFragment();
Bundle args = new Bundle();
args.putParcelable(AccountSettingsActivity.ACCOUNT, account);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
account = getArguments().getParcelable(ACCOUNT);
viewModel = ViewModelProviders.of(this).get(ManageFeedsViewModel.class); viewModel = ViewModelProviders.of(this).get(ManageFeedsViewModel.class);
viewModel.setAccount(account); viewModel.setAccount(account);
recyclerView = findViewById(R.id.feeds_recyclerview); viewModel.getFeedsWithFolder().observe(this, feedWithFolders -> adapter.submitList(feedWithFolders));
recyclerView.setLayoutManager(new LinearLayoutManager(this)); }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_feeds, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.feedsRecyclerview.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new FeedsAdapter(new FeedsAdapter.ManageFeedsListener() { adapter = new FeedsAdapter(new FeedsAdapter.ManageFeedsListener() {
@Override @Override
@ -61,7 +96,7 @@ public class ManageFeedsActivity extends AppCompatActivity {
@Override @Override
public void onOpenLink(FeedWithFolder feedWithFolder) { public void onOpenLink(FeedWithFolder feedWithFolder) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); Vibrator vibrator = (Vibrator) getActivity().getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(50); vibrator.vibrate(50);
Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(feedWithFolder.getFeed().getSiteUrl())); Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(feedWithFolder.getFeed().getSiteUrl()));
@ -69,7 +104,7 @@ public class ManageFeedsActivity extends AppCompatActivity {
} }
}); });
recyclerView.setAdapter(adapter); binding.feedsRecyclerview.setAdapter(adapter);
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override @Override
@ -96,13 +131,11 @@ public class ManageFeedsActivity extends AppCompatActivity {
return true; return true;
} }
}).attachToRecyclerView(recyclerView); }).attachToRecyclerView(binding.feedsRecyclerview);
viewModel.getFeedsWithFolder().observe(this, feedWithFolders -> adapter.submitList(feedWithFolders));
} }
private void deleteFolder(int feedId, int position) { private void deleteFolder(int feedId, int position) {
new MaterialDialog.Builder(this) new MaterialDialog.Builder(getContext())
.title(getString(R.string.delete_feed)) .title(getString(R.string.delete_feed))
.positiveText(getString(R.string.validate)) .positiveText(getString(R.string.validate))
.negativeText(getString(R.string.cancel)) .negativeText(getString(R.string.cancel))
@ -112,12 +145,12 @@ public class ManageFeedsActivity extends AppCompatActivity {
.subscribe(new DisposableCompletableObserver() { .subscribe(new DisposableCompletableObserver() {
@Override @Override
public void onComplete() { public void onComplete() {
Toast.makeText(getApplication(), "feed deleted", Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), "feed deleted", Toast.LENGTH_LONG).show();
} }
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Toast.makeText(getApplication(), "error on feed deletion", Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), "error on feed deletion", Toast.LENGTH_LONG).show();
} }
})) }))
.onNegative(((dialog, which) -> adapter.notifyItemChanged(position))) .onNegative(((dialog, which) -> adapter.notifyItemChanged(position)))
@ -129,20 +162,21 @@ public class ManageFeedsActivity extends AppCompatActivity {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("feedWithFolder", feedWithFolder); bundle.putParcelable("feedWithFolder", feedWithFolder);
bundle.putParcelable(ACCOUNT, account);
editFeedDialog.setArguments(bundle); editFeedDialog.setArguments(bundle);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.add(editFeedDialog, "").commit(); transaction.add(editFeedDialog, "").commit();
} }
private void addFolder() { private void addFolder() {
new MaterialDialog.Builder(this) new MaterialDialog.Builder(getActivity())
.title(R.string.add_folder) .title(R.string.add_folder)
.positiveText(R.string.validate) .positiveText(R.string.validate)
.input(R.string.folder, 0, (dialog, input) -> { .input(R.string.folder, 0, (dialog, input) -> {
Folder folder = new Folder(input.toString()); Folder folder = new Folder(input.toString());
folder.setAccountId(1); // TODO add account support for creating folders folder.setAccountId(account.getId());
viewModel.addFolder(folder) viewModel.addFolder(folder)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -150,41 +184,15 @@ public class ManageFeedsActivity extends AppCompatActivity {
.subscribe(new DisposableCompletableObserver() { .subscribe(new DisposableCompletableObserver() {
@Override @Override
public void onComplete() { public void onComplete() {
Toast.makeText(getApplication(), "folder inserted", Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), "folder inserted", Toast.LENGTH_LONG).show();
} }
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Toast.makeText(getApplication(), "error on folder insertion", Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), "error on folder insertion", Toast.LENGTH_LONG).show();
} }
}); });
}) })
.show(); .show();
} }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.feeds_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.add_folder:
addFolder();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
finish();
super.onBackPressed();
}
} }

View File

@ -0,0 +1,42 @@
package com.readrops.app.fragments;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.readrops.app.R;
import com.readrops.app.database.entities.Account;
public class FoldersFragment extends Fragment {
public FoldersFragment() {
// Required empty public constructor
}
public static FoldersFragment newInstance(Account account) {
FoldersFragment fragment = new FoldersFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_folders, container, false);
}
}

View File

@ -15,6 +15,8 @@ import androidx.lifecycle.ViewModelProviders;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.readrops.app.R; import com.readrops.app.R;
import com.readrops.app.activities.ManageFeedsFoldersActivity;
import com.readrops.app.database.entities.Account;
import com.readrops.app.database.entities.Feed; import com.readrops.app.database.entities.Feed;
import com.readrops.app.database.entities.Folder; import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.pojo.FeedWithFolder; import com.readrops.app.database.pojo.FeedWithFolder;
@ -30,16 +32,21 @@ public class EditFeedDialog extends DialogFragment implements AdapterView.OnItem
private TextInputEditText feedUrl; private TextInputEditText feedUrl;
private Spinner folder; private Spinner folder;
Map<String, Integer> values; private Map<String, Integer> values;
private FeedWithFolder feedWithFolder; private FeedWithFolder feedWithFolder;
private Account account;
private ManageFeedsViewModel viewModel; private ManageFeedsViewModel viewModel;
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
viewModel = ViewModelProviders.of(getActivity()).get(ManageFeedsViewModel.class); viewModel = ViewModelProviders.of(getActivity()).get(ManageFeedsViewModel.class);
feedWithFolder = getArguments().getParcelable("feedWithFolder"); feedWithFolder = getArguments().getParcelable("feedWithFolder");
account = getArguments().getParcelable(ManageFeedsFoldersActivity.ACCOUNT);
viewModel.setAccount(account);
View v = getActivity().getLayoutInflater().inflate(R.layout.edit_feed_layout, null); View v = getActivity().getLayoutInflater().inflate(R.layout.edit_feed_layout, null);
@ -53,8 +60,6 @@ public class EditFeedDialog extends DialogFragment implements AdapterView.OnItem
viewModel.updateFeedWithFolder(feedWithFolder); viewModel.updateFeedWithFolder(feedWithFolder);
}); });
builder.setView(v); builder.setView(v);
fillData(v); fillData(v);

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.ManageFeedsActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/feeds_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listItem="@layout/feed_layout">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".activities.ManageFeedsFoldersActivity">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme">
<androidx.appcompat.widget.Toolbar
android:id="@+id/manage_feeds_folders_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:theme="@style/AppTheme"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/manage_feeds_folders_tablayout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/manage_feeds_folders_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".fragments.FeedsFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/feeds_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listItem="@layout/feed_layout">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.FoldersFragment">
</FrameLayout>