Drag to move timelines
This commit is contained in:
parent
a528d878e5
commit
94aba5f3a0
|
@ -0,0 +1,241 @@
|
||||||
|
package fr.gouv.etalab.mastodon.drawers;
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Paul Burke
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v4.view.MotionEventCompat;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.ManageTimelines;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.RemoteInstance;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.itemtouchhelper.ItemTouchHelperAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.itemtouchhelper.ItemTouchHelperViewHolder;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.itemtouchhelper.OnStartDragListener;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.InstancesDAO;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.TimelinesDAO;
|
||||||
|
|
||||||
|
import static fr.gouv.etalab.mastodon.helper.Helper.THEME_LIGHT;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple RecyclerView.Adapter that implements {@link ItemTouchHelperAdapter} to respond to move and
|
||||||
|
* dismiss events from a {@link android.support.v7.widget.helper.ItemTouchHelper}.
|
||||||
|
*
|
||||||
|
* @author Paul Burke (ipaulpro)
|
||||||
|
*/
|
||||||
|
public class ReorderTabAdapter extends RecyclerView.Adapter<ReorderTabAdapter.ItemViewHolder> implements ItemTouchHelperAdapter {
|
||||||
|
|
||||||
|
private List<ManageTimelines> mItems;
|
||||||
|
|
||||||
|
private final OnStartDragListener mDragStartListener;
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private SharedPreferences sharedpreferences;
|
||||||
|
public ReorderTabAdapter(Context context, List<ManageTimelines> manageTimelines, OnStartDragListener dragStartListener) {
|
||||||
|
this. mDragStartListener = dragStartListener;
|
||||||
|
this.mItems = manageTimelines;
|
||||||
|
this.context = context;
|
||||||
|
sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ItemViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.drawer_reorder, parent, false);
|
||||||
|
return new ItemViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NotNull final ItemViewHolder holder, int position) {
|
||||||
|
|
||||||
|
|
||||||
|
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
|
||||||
|
ManageTimelines tl = mItems.get(position);
|
||||||
|
switch (tl.getType()){
|
||||||
|
case HOME:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_home);
|
||||||
|
holder.textView.setText(context.getString(R.string.home_menu));
|
||||||
|
break;
|
||||||
|
case NOTIFICATION:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_notifications);
|
||||||
|
holder.textView.setText(context.getString(R.string.notifications));
|
||||||
|
break;
|
||||||
|
case DIRECT:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_direct_messages);
|
||||||
|
holder.textView.setText(context.getString(R.string.direct_message));
|
||||||
|
break;
|
||||||
|
case LOCAL:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_people);
|
||||||
|
holder.textView.setText(context.getString(R.string.local_menu));
|
||||||
|
break;
|
||||||
|
case PUBLIC:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_public);
|
||||||
|
holder.textView.setText(context.getString(R.string.global_menu));
|
||||||
|
break;
|
||||||
|
case ART:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_color_lens);
|
||||||
|
holder.textView.setText(context.getString(R.string.art_menu));
|
||||||
|
break;
|
||||||
|
case PEERTUBE:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_video_peertube);
|
||||||
|
holder.textView.setText(context.getString(R.string.peertube_menu));
|
||||||
|
break;
|
||||||
|
case INSTANCE:
|
||||||
|
switch ( tl.getRemoteInstance().getType()){
|
||||||
|
case "PEERTUBE":
|
||||||
|
holder.iconView.setImageResource(R.drawable.peertube_icon);
|
||||||
|
break;
|
||||||
|
case "MASTODON":
|
||||||
|
holder.iconView.setImageResource(R.drawable.mastodon_icon);
|
||||||
|
break;
|
||||||
|
case "PIXELFED":
|
||||||
|
holder.iconView.setImageResource(R.drawable.pixelfed);
|
||||||
|
break;
|
||||||
|
case "MISSKEY":
|
||||||
|
holder.iconView.setImageResource(R.drawable.misskey);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
holder.textView.setText( tl.getRemoteInstance().getHost());
|
||||||
|
break;
|
||||||
|
case TAG:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_tag_timeline);
|
||||||
|
if( tl.getTagTimeline().getDisplayname() != null)
|
||||||
|
holder.textView.setText( tl.getTagTimeline().getDisplayname());
|
||||||
|
else
|
||||||
|
holder.textView.setText( tl.getTagTimeline().getName());
|
||||||
|
break;
|
||||||
|
case LIST:
|
||||||
|
holder.iconView.setImageResource(R.drawable.ic_list);
|
||||||
|
holder.textView.setText( tl.getListTimeline().getTitle());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( tl.getType() != ManageTimelines.Type.INSTANCE){
|
||||||
|
if (theme == THEME_LIGHT) {
|
||||||
|
holder.iconView.setColorFilter(ContextCompat.getColor(context, R.color.action_light_header), PorterDuff.Mode.SRC_IN);
|
||||||
|
} else {
|
||||||
|
holder.iconView.setColorFilter(ContextCompat.getColor(context, R.color.dark_text), PorterDuff.Mode.SRC_IN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theme == THEME_LIGHT) {
|
||||||
|
holder.handleView.setColorFilter(ContextCompat.getColor(context, R.color.action_light_header), PorterDuff.Mode.SRC_IN);
|
||||||
|
holder.hideView.setColorFilter(ContextCompat.getColor(context, R.color.action_light_header), PorterDuff.Mode.SRC_IN);
|
||||||
|
} else {
|
||||||
|
holder.handleView.setColorFilter(ContextCompat.getColor(context, R.color.dark_text), PorterDuff.Mode.SRC_IN);
|
||||||
|
holder.hideView.setColorFilter(ContextCompat.getColor(context, R.color.dark_text), PorterDuff.Mode.SRC_IN);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.hideView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
tl.setDisplayed(! tl.isDisplayed());
|
||||||
|
if(tl.isDisplayed()){
|
||||||
|
holder.handleView.setImageResource(R.drawable.ic_make_tab_unvisible);
|
||||||
|
}else{
|
||||||
|
holder.handleView.setImageResource(R.drawable.ic_make_tab_visible);
|
||||||
|
}
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
new TimelinesDAO(context, db).update(tl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start a drag whenever the handle view it touched
|
||||||
|
holder.handleView.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
|
||||||
|
mDragStartListener.onStartDrag(holder);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemDismiss(int position) {
|
||||||
|
mItems.remove(position);
|
||||||
|
notifyItemRemoved(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onItemMove(int fromPosition, int toPosition) {
|
||||||
|
Collections.swap(mItems, fromPosition, toPosition);
|
||||||
|
notifyItemMoved(fromPosition, toPosition);
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
for(ManageTimelines timelines: mItems){
|
||||||
|
new TimelinesDAO(context, db).update(timelines);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mItems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple example of a view holder that implements {@link ItemTouchHelperViewHolder} and has a
|
||||||
|
* "handle" view that initiates a drag event when touched.
|
||||||
|
*/
|
||||||
|
public class ItemViewHolder extends RecyclerView.ViewHolder implements
|
||||||
|
ItemTouchHelperViewHolder {
|
||||||
|
|
||||||
|
final TextView textView;
|
||||||
|
final ImageView handleView;
|
||||||
|
final ImageView hideView;
|
||||||
|
final ImageView iconView;
|
||||||
|
|
||||||
|
ItemViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
textView = itemView.findViewById(R.id.text);
|
||||||
|
handleView = itemView.findViewById(R.id.handle);
|
||||||
|
iconView = itemView.findViewById(R.id.icon);
|
||||||
|
hideView = itemView.findViewById(R.id.hide);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemSelected() {
|
||||||
|
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
|
||||||
|
itemView.setBackgroundColor(Color.LTGRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClear() {
|
||||||
|
itemView.setBackgroundColor(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package fr.gouv.etalab.mastodon.fragments;
|
||||||
|
/* Copyright 2019 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastalab
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Mastalab 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 for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Mastalab; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.ManageTimelines;
|
||||||
|
import fr.gouv.etalab.mastodon.drawers.ReorderTabAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.itemtouchhelper.OnStartDragListener;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.TimelinesDAO;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 31/03/2019.
|
||||||
|
* Fragment to display tags
|
||||||
|
*/
|
||||||
|
public class DisplayReorderTabFragment extends Fragment implements OnStartDragListener {
|
||||||
|
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_reorder_tabs, container, false);
|
||||||
|
context = getContext();
|
||||||
|
|
||||||
|
RecyclerView lv_reorder_tabs = rootView.findViewById(R.id.lv_reorder_tabs);
|
||||||
|
LinearLayoutManager mLayoutManager = new LinearLayoutManager(context);
|
||||||
|
lv_reorder_tabs.setLayoutManager(mLayoutManager);
|
||||||
|
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
List<ManageTimelines> timelines = new TimelinesDAO(context, db).getAllTimelines();
|
||||||
|
new ReorderTabAdapter(context, timelines, DisplayReorderTabFragment.this);
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle saveInstance) {
|
||||||
|
super.onCreate(saveInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package fr.gouv.etalab.mastodon.helper.itemtouchhelper;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Paul Burke
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to listen for a move or dismissal event from a {@link ItemTouchHelper.Callback}.
|
||||||
|
*
|
||||||
|
* @author Paul Burke (ipaulpro)
|
||||||
|
*/
|
||||||
|
public interface ItemTouchHelperAdapter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an item has been dragged far enough to trigger a move. This is called every time
|
||||||
|
* an item is shifted, and <strong>not</strong> at the end of a "drop" event.<br/>
|
||||||
|
* <br/>
|
||||||
|
* Implementations should call {@link RecyclerView.Adapter#notifyItemMoved(int, int)} after
|
||||||
|
* adjusting the underlying data to reflect this move.
|
||||||
|
*
|
||||||
|
* @param fromPosition The start position of the moved item.
|
||||||
|
* @param toPosition Then resolved position of the moved item.
|
||||||
|
* @return True if the item was moved to the new adapter position.
|
||||||
|
*
|
||||||
|
* @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
|
||||||
|
* @see RecyclerView.ViewHolder#getAdapterPosition()
|
||||||
|
*/
|
||||||
|
boolean onItemMove(int fromPosition, int toPosition);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an item has been dismissed by a swipe.<br/>
|
||||||
|
* <br/>
|
||||||
|
* Implementations should call {@link RecyclerView.Adapter#notifyItemRemoved(int)} after
|
||||||
|
* adjusting the underlying data to reflect this removal.
|
||||||
|
*
|
||||||
|
* @param position The position of the item dismissed.
|
||||||
|
*
|
||||||
|
* @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
|
||||||
|
* @see RecyclerView.ViewHolder#getAdapterPosition()
|
||||||
|
*/
|
||||||
|
void onItemDismiss(int position);
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package fr.gouv.etalab.mastodon.helper.itemtouchhelper;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Paul Burke
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to notify an item ViewHolder of relevant callbacks from {@link
|
||||||
|
* android.support.v7.widget.helper.ItemTouchHelper.Callback}.
|
||||||
|
*
|
||||||
|
* @author Paul Burke (ipaulpro)
|
||||||
|
*/
|
||||||
|
public interface ItemTouchHelperViewHolder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the {@link ItemTouchHelper} first registers an item as being moved or swiped.
|
||||||
|
* Implementations should update the item view to indicate it's active state.
|
||||||
|
*/
|
||||||
|
void onItemSelected();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the {@link ItemTouchHelper} has completed the move or swipe, and the active item
|
||||||
|
* state should be cleared.
|
||||||
|
*/
|
||||||
|
void onItemClear();
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package fr.gouv.etalab.mastodon.helper.itemtouchhelper;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Paul Burke
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for manual initiation of a drag.
|
||||||
|
*/
|
||||||
|
public interface OnStartDragListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a view is requesting a start of a drag.
|
||||||
|
*
|
||||||
|
* @param viewHolder The holder of the view to drag.
|
||||||
|
*/
|
||||||
|
void onStartDrag(RecyclerView.ViewHolder viewHolder);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
package fr.gouv.etalab.mastodon.helper.itemtouchhelper;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Paul Burke
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ItemTouchHelper.Callback} that enables basic drag & drop and
|
||||||
|
* swipe-to-dismiss. Drag events are automatically started by an item long-press.<br/>
|
||||||
|
* </br/>
|
||||||
|
* Expects the <code>RecyclerView.Adapter</code> to listen for {@link
|
||||||
|
* ItemTouchHelperAdapter} callbacks and the <code>RecyclerView.ViewHolder</code> to implement
|
||||||
|
* {@link ItemTouchHelperViewHolder}.
|
||||||
|
*
|
||||||
|
* @author Paul Burke (ipaulpro)
|
||||||
|
*/
|
||||||
|
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
|
||||||
|
|
||||||
|
public static final float ALPHA_FULL = 1.0f;
|
||||||
|
|
||||||
|
private final ItemTouchHelperAdapter mAdapter;
|
||||||
|
|
||||||
|
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
|
||||||
|
mAdapter = adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLongPressDragEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItemViewSwipeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||||
|
// Set movement flags based on the layout manager
|
||||||
|
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
|
||||||
|
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||||
|
final int swipeFlags = 0;
|
||||||
|
return makeMovementFlags(dragFlags, swipeFlags);
|
||||||
|
} else {
|
||||||
|
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
|
||||||
|
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
|
||||||
|
return makeMovementFlags(dragFlags, swipeFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
|
||||||
|
if (source.getItemViewType() != target.getItemViewType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify the adapter of the move
|
||||||
|
mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
|
||||||
|
// Notify the adapter of the dismissal
|
||||||
|
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
|
||||||
|
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
|
||||||
|
// Fade out the view as it is swiped out of the parent's bounds
|
||||||
|
final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
|
||||||
|
viewHolder.itemView.setAlpha(alpha);
|
||||||
|
viewHolder.itemView.setTranslationX(dX);
|
||||||
|
} else {
|
||||||
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
|
||||||
|
// We only want the active item to change
|
||||||
|
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
|
||||||
|
if (viewHolder instanceof ItemTouchHelperViewHolder) {
|
||||||
|
// Let the view holder know that this item is being moved or dragged
|
||||||
|
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
|
||||||
|
itemViewHolder.onItemSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onSelectedChanged(viewHolder, actionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||||
|
super.clearView(recyclerView, viewHolder);
|
||||||
|
|
||||||
|
viewHolder.itemView.setAlpha(ALPHA_FULL);
|
||||||
|
|
||||||
|
if (viewHolder instanceof ItemTouchHelperViewHolder) {
|
||||||
|
// Tell the view holder it's time to restore the idle state
|
||||||
|
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
|
||||||
|
itemViewHolder.onItemClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4v2z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M3,13h2v-2L3,11v2zM3,17h2v-2L3,15v2zM3,9h2L5,7L3,7v2zM7,13h14v-2L7,11v2zM7,17h14v-2L7,15v2zM7,7v2h14L21,7L7,7z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M17.63,5.84C17.27,5.33 16.67,5 16,5L5,5.01C3.9,5.01 3,5.9 3,7v10c0,1.1 0.9,1.99 2,1.99L16,19c0.67,0 1.27,-0.33 1.63,-0.84L22,12l-4.37,-6.16z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2015 Paul Burke
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/item"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?listPreferredItemHeight"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:foreground="?selectableItemBackground">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="?listPreferredItemHeight"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical|left"
|
||||||
|
android:scaleType="center"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/hide"
|
||||||
|
android:layout_width="?listPreferredItemHeight"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical|right"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@drawable/ic_make_tab_unvisible"
|
||||||
|
android:contentDescription="@string/hide_timeline"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/handle"
|
||||||
|
android:layout_width="?listPreferredItemHeight"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical|right"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@drawable/ic_drag_handle"
|
||||||
|
android:contentDescription="@string/move_timeline"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
</FrameLayout>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2019 Thomas Schneider
|
||||||
|
|
||||||
|
This file is a part of Mastalab
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Mastalab 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 for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with Mastalab; if not,
|
||||||
|
see <http://www.gnu.org/licenses>.
|
||||||
|
-->
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:paddingLeft="@dimen/fab_margin"
|
||||||
|
android:paddingRight="@dimen/fab_margin"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/lv_reorder_tabs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="?attr/actionBarSize"
|
||||||
|
android:scrollbars="none"
|
||||||
|
>
|
||||||
|
</android.support.v7.widget.RecyclerView>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
|
@ -920,6 +920,9 @@
|
||||||
<string name="notif_poll">A poll you have voted in has ended</string>
|
<string name="notif_poll">A poll you have voted in has ended</string>
|
||||||
<string name="set_display_peertube">Display Peertube timeline</string>
|
<string name="set_display_peertube">Display Peertube timeline</string>
|
||||||
<string name="peertube_menu">Peertube</string>
|
<string name="peertube_menu">Peertube</string>
|
||||||
|
<string name="hide_tab">Hide the tab</string>
|
||||||
|
<string name="move_timeline">Move timeline</string>
|
||||||
|
<string name="hide_timeline">Hide timeline</string>
|
||||||
|
|
||||||
<plurals name="number_of_vote">
|
<plurals name="number_of_vote">
|
||||||
<item quantity="one">%d vote</item>
|
<item quantity="one">%d vote</item>
|
||||||
|
|
Loading…
Reference in New Issue