Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds ability to rearrange ballot items #3

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,19 @@
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import ch.threema.app.R;
import ch.threema.app.adapters.ballot.BallotWizard1ListAdapter;
import ch.threema.app.adapters.ballot.BallotWizard1Adapter;
import ch.threema.app.dialogs.DateSelectorDialog;
import ch.threema.app.dialogs.TimeSelectorDialog;
import ch.threema.app.utils.EditTextUtil;
Expand All @@ -52,13 +56,15 @@ public class BallotWizardFragment1 extends BallotWizardFragment implements DateS
private static final String DIALOG_TAG_SELECT_TIME = "selectTime";
private static final String DIALOG_TAG_SELECT_DATETIME = "selectDateTime";

private ListView choiceListView;
private RecyclerView choiceRecyclerView;
private List<BallotChoiceModel> ballotChoiceModelList;
private BallotWizard1ListAdapter listAdapter = null;
private BallotWizard1Adapter listAdapter = null;
private ImageButton createChoiceButton;
private ImageButton addDateButton, addDateTimeButton;
private EditText createChoiceEditText;
private Date originalDate = null;
private LinearLayoutManager choiceRecyclerViewLayoutManager;
private int lastVisibleBallotPosition;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Expand All @@ -67,7 +73,61 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.fragment_ballot_wizard1, container, false);

this.choiceListView = rootView.findViewById(R.id.ballot_list);
this.choiceRecyclerView = rootView.findViewById(R.id.ballot_list);
this.choiceRecyclerViewLayoutManager = new LinearLayoutManager(getActivity());
this.choiceRecyclerView.setLayoutManager(choiceRecyclerViewLayoutManager);
this.choiceRecyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (bottom < oldBottom) {
choiceRecyclerView.post(new Runnable() {
@Override
public void run() {
choiceRecyclerView.smoothScrollToPosition(lastVisibleBallotPosition);
}
});
}
}
});
this.choiceRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
lastVisibleBallotPosition = choiceRecyclerViewLayoutManager.findLastVisibleItemPosition();
}
}
});
int moveUpDown = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
ItemTouchHelper.Callback swipeCallback = new ItemTouchHelper.SimpleCallback(moveUpDown, 0) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(ballotChoiceModelList, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(ballotChoiceModelList, i, i - 1);
}
}
listAdapter.notifyItemMoved(fromPosition, toPosition);
return true;
}

@Override
public boolean isItemViewSwipeEnabled() {
return false;
}

@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeCallback);
itemTouchHelper.attachToRecyclerView(choiceRecyclerView);

this.createChoiceEditText = rootView.findViewById(R.id.create_choice_name);
this.createChoiceEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
Expand Down Expand Up @@ -133,19 +193,16 @@ public void onClick(View v) {
private void initAdapter() {
if(this.getBallotActivity() != null) {
this.ballotChoiceModelList = this.getBallotActivity().getBallotChoiceModelList();
this.listAdapter = new BallotWizard1ListAdapter(getActivity(), this.ballotChoiceModelList);

this.listAdapter.setOnChoiceListener(new BallotWizard1ListAdapter.OnChoiceListener() {
@Override
public void onRemoveClicked(BallotChoiceModel choiceModel) {
synchronized (ballotChoiceModelList) {
ballotChoiceModelList.remove(choiceModel);
listAdapter.notifyDataSetChanged();
}
}
});
this.listAdapter = new BallotWizard1Adapter(this.ballotChoiceModelList);
this.listAdapter.setOnChoiceListener(this::removeChoice);
this.choiceRecyclerView.setAdapter(this.listAdapter);
}
}

this.choiceListView.setAdapter(this.listAdapter);
private void removeChoice(int position) {
synchronized (ballotChoiceModelList) {
ballotChoiceModelList.remove(position);
listAdapter.notifyItemRemoved(position);
}
}

Expand All @@ -158,7 +215,9 @@ private void createChoice() {
String text = createChoiceEditText.getText().toString();
if (!TestUtil.empty(text)) {
createChoice(text.trim(), BallotChoiceModel.Type.Text);
listAdapter.notifyDataSetChanged();
int insertPosition = this.ballotChoiceModelList.size() - 1;
listAdapter.notifyItemInserted(insertPosition);
choiceRecyclerView.smoothScrollToPosition(insertPosition);
createChoiceEditText.setText("");
createChoiceEditText.post(new Runnable() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* _____ _
* |_ _| |_ _ _ ___ ___ _ __ __ _
* | | | ' \| '_/ -_) -_) ' \/ _` |_
* |_| |_||_|_| \___\___|_|_|_\__,_(_)
*
* Threema for Android
* Copyright (c) 2014-2021 Threema GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package ch.threema.app.adapters.ballot;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import ch.threema.app.R;
import ch.threema.storage.models.ballot.BallotChoiceModel;

/**
*
*/
public class BallotWizard1Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

public interface OnChoiceListener {
void onRemoveClicked(int position);
}

private static class BallotAdminChoiceItemHolder extends RecyclerView.ViewHolder {

public TextView name;
public ImageView removeButton;

public BallotAdminChoiceItemHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.choice_name_readonly);
removeButton = itemView.findViewById(R.id.remove_button);
}

public void bind(BallotChoiceModel choiceModel, OnChoiceListener onChoiceListener) {
if (choiceModel != null) {
name.setText(choiceModel.getName());
if (canEdit(choiceModel)) {
removeButton.setOnClickListener(view -> {
if (onChoiceListener != null) {
onChoiceListener.onRemoveClicked(getAdapterPosition());
}
});
removeButton.setVisibility(View.VISIBLE);
} else {
removeButton.setVisibility(View.GONE);
}
}
}

private boolean canEdit(BallotChoiceModel choiceModel) {
return choiceModel.getId() <= 0;
}
}

private final List<BallotChoiceModel> values;
private OnChoiceListener onChoiceListener;

public BallotWizard1Adapter(List<BallotChoiceModel> values) {
this.values = values;
}

public BallotWizard1Adapter setOnChoiceListener(OnChoiceListener onChoiceListener) {
this.onChoiceListener = onChoiceListener;
return this;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.item_ballot_wizard1, parent, false);
return new BallotAdminChoiceItemHolder(view);
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
BallotAdminChoiceItemHolder viewHolder = (BallotAdminChoiceItemHolder) holder;
viewHolder.bind(values.get(position), onChoiceListener);
}

@Override
public int getItemCount() {
return values.size();
}
}

This file was deleted.

3 changes: 1 addition & 2 deletions app/src/main/res/layout/fragment_ballot_wizard1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@
android:textSize="24sp"
/>

<ListView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/ballot_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="14dp"
android:divider="@android:color/transparent"
android:dividerHeight="2dp"
android:transcriptMode="alwaysScroll"
/>

<RelativeLayout
Expand Down