-
-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
194 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package snow.music.util; | ||
|
||
import androidx.annotation.NonNull; | ||
import androidx.recyclerview.widget.ItemTouchHelper; | ||
import androidx.recyclerview.widget.RecyclerView; | ||
|
||
import java.util.Objects; | ||
|
||
/** | ||
* 列表项拖拽回调。 | ||
*/ | ||
public class ItemDragCallback extends ItemTouchHelper.Callback { | ||
private boolean mDragging = false; | ||
private int mFromPosition = -1; | ||
|
||
private final OnDragCallback mCallback; | ||
|
||
public ItemDragCallback(@NonNull OnDragCallback callback) { | ||
Objects.requireNonNull(callback); | ||
mCallback = 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) { | ||
if (!mDragging) { | ||
mDragging = true; | ||
mFromPosition = viewHolder.getBindingAdapterPosition(); | ||
} | ||
|
||
mCallback.onDragging(viewHolder.getBindingAdapterPosition(), target.getBindingAdapterPosition()); | ||
|
||
return true; | ||
} | ||
|
||
@Override | ||
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { | ||
// ignore | ||
} | ||
|
||
@Override | ||
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { | ||
super.clearView(recyclerView, viewHolder); | ||
|
||
if (mFromPosition == -1) { | ||
return; | ||
} | ||
|
||
int fromPosition = mFromPosition; | ||
int toPosition = viewHolder.getBindingAdapterPosition(); | ||
|
||
clearDraggingState(); | ||
if (toPosition == fromPosition) { | ||
return; | ||
} | ||
|
||
mCallback.onDragComplete(fromPosition, toPosition); | ||
} | ||
|
||
private void clearDraggingState() { | ||
mDragging = false; | ||
mFromPosition = -1; | ||
} | ||
|
||
public interface OnDragCallback { | ||
void onDragging(int from, int target); | ||
|
||
void onDragComplete(int fromPosition, int toPosition); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
player/src/main/java/snow/player/util/MovablePlaylist.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package snow.player.util; | ||
|
||
import androidx.annotation.NonNull; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
import snow.player.audio.MusicItem; | ||
import snow.player.playlist.Playlist; | ||
|
||
/** | ||
* 该类用于帮助实现可拖拽播放列表。 | ||
* <p> | ||
* 当拖拽列表时,可以在 {@code ItemTouchHelper.Callback} 的 {@code onMove} 方法中调用 | ||
* {@link #move(int, int)} 方法交换列表项位置。该方法会在移动列表项位置时修正当前正在播放的歌曲在播放队列中的位置, | ||
* 移动歌曲后,可以使用 {@link #getPlayPosition()} 获取到正确的当前正在播放歌曲的位置。 | ||
*/ | ||
public class MovablePlaylist { | ||
private final List<MusicItem> mMusicItems; | ||
private int mPlayPosition; | ||
|
||
public MovablePlaylist(@NonNull Playlist playlist, int playPosition) { | ||
Objects.requireNonNull(playlist); | ||
|
||
mMusicItems = new ArrayList<>(playlist.getAllMusicItem()); | ||
mPlayPosition = playPosition; | ||
} | ||
|
||
/** | ||
* 移动歌曲。 | ||
* <p> | ||
* 移动歌曲后,当前正在播放的歌曲在播放队列中的位置可能也会改变。 | ||
* | ||
* @param fromPosition 要移动的歌曲的位置。 | ||
* @param toPosition 歌曲要移动到的位置。 | ||
*/ | ||
public void move(int fromPosition, int toPosition) { | ||
if (fromPosition == toPosition) { | ||
return; | ||
} | ||
|
||
mMusicItems.add(toPosition, mMusicItems.remove(fromPosition)); | ||
updatePlayPosition(fromPosition, toPosition); | ||
} | ||
|
||
private void updatePlayPosition(int fromPosition, int toPosition) { | ||
int playPosition = mPlayPosition; | ||
|
||
if (notInRegion(playPosition, fromPosition, toPosition)) { | ||
return; | ||
} | ||
|
||
if (fromPosition < playPosition) { | ||
playPosition -= 1; | ||
} else if (fromPosition == playPosition) { | ||
playPosition = toPosition; | ||
} else { | ||
playPosition += 1; | ||
} | ||
|
||
mPlayPosition = playPosition; | ||
} | ||
|
||
private boolean notInRegion(int position, int fromPosition, int toPosition) { | ||
return position > Math.max(fromPosition, toPosition) || position < Math.min(fromPosition, toPosition); | ||
} | ||
|
||
public int getPlayPosition() { | ||
return mPlayPosition; | ||
} | ||
|
||
public MusicItem get(int index) { | ||
return mMusicItems.get(index); | ||
} | ||
|
||
public int size() { | ||
return mMusicItems.size(); | ||
} | ||
|
||
public boolean isEmpty() { | ||
return mMusicItems.isEmpty(); | ||
} | ||
} |