欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義控件之小說書架實現(xiàn)示例詳解

 更新時間:2023年04月18日 08:46:40   作者:鹵肉拌面  
這篇文章主要為大家介紹了Android自定義控件之小說書架示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪方法

前言

在手機看小說的時候,看到一個很有意思的效果,在UC瀏覽器切換到小說書架時候,可以在這個界面手指長按一本書拖拽它,當拖拽到其他小說后面時候??梢詫⑵渌≌f前置,拖拽的小說到該位置上。功能效果大致如下圖所示:

功能分析

通過運行圖可以看出,該程序主要功能包括
1.按照網(wǎng)格布局展示小說信息
2.手指長按單個小說時,可拖拽該小說,并且手指松開時,將拖拽小說插入到該位置,其他小說依次向移動
3.選中要刪除的小說,點擊刪除按鈕刪除
其中有些難度的是小說的拖拽,主要是拖拽需要注意的地方比較多。

代碼實現(xiàn)

小說的展示

我這里是使用RecyclerView實現(xiàn),只不過layoutManager是使用GridLayoutManager,代碼如下:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/rl_bookshelf"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:spanCount="3"
    app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
    tools:listitem="@layout/item_bookshelf"/>

小說拖拽BookShelfItemTouchHelper實現(xiàn)

RecyclerView想要實現(xiàn)拖拽功能需要寫一個繼承ItemTouchHelper.Callback的類,這里把這個類命名為BookShelfItemTouchHelper。如果想要一個RecyclerView可以實現(xiàn)拖拽,可以給這個RecyclerView添加ItemTouchHelper,binding.rlBookshelf是想要添加拖拽效果的RecyclerView,設置代碼如下:

val itemTouchHelper = ItemTouchHelper(BookShelfItemTouchHelper(books,adapter))
itemTouchHelper.attachToRecyclerView(binding.rlBookshelf)

關于BookShelfItemTouchHelper這個類的實現(xiàn),需要重寫下面幾個方法:

getMovementFlags:可以拖動和滑動的方向,最后通過 makeMovementFlags 方法將拖拽和滑動方向匯總起來。代碼里面是設置可以上下左右拖動,不設置滑動。

onMove:這個方法是,當手指移動到某個item上時,會觸發(fā)這個函數(shù)(個人理解這個函數(shù)觸發(fā)時機是,當手指拖拽item在目標view上停留了一小會),這個方法里面viewHolder參數(shù)是手指拖拽item的ViewHolde,target是目標item的ViewHolder。在這里我們是把拖拽item放到目標item位置上,并返回true。方法末尾,還需要調(diào)用Adapter的notifyItemMoved()方法,告訴RecyclerView這兩個item發(fā)生了變換,并重繪。關于托拽item與目標item位置變換,如果我們把拖動的item位置看為fromPosition,把目標item的位置看為toPosition。我們需要把拖拽item放到目標item位置上,并比較fromPosition和toPosition大小來決定,fromPosition與toPositon之間item是前移還是后移。代碼如下:

@Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        int fromPosition = viewHolder.getAdapterPosition();
        int toPosition = target.getAdapterPosition();   bookshelfAdapter.notifyItemRangeChanged(Math.min(fromPosition,toPosition),Math.abs(fromPosition - toPosition) + 1);
        if (fromPosition < toPosition){
            for (int i = fromPosition;i<toPosition;i++){
                Collections.swap(books,i,i+1);
            }
        }else {
            for (int i = fromPosition; i > toPosition;i--){
                Collections.swap(books,i,i-1);
            }
        }
        bookshelfAdapter.notifyItemMoved(fromPosition,toPosition);
        return true;
    }

onMoved:onMove返回true會觸發(fā)這個方法,在這個方法里需要調(diào)用Adapter的notifyItemRangeChanged()方法來批量更新,item位置變換過程中受影響的數(shù)據(jù)。

onSelectedChanged():當手指長按選中item時會觸發(fā)這個方法,這個方法中,我修改了item的背景色并稍微擴大item的寬高。

clearView:當手指松開時會觸發(fā)該方法,在這個方法里面,是恢復item的寬高及背景色。

interpolateOutOfBoundsScroll:這個方法是可以設置滾動速度,如果不修改的話,會發(fā)現(xiàn)拖拽item到頂部或底部時候,向上或下的速度很慢,在這里設置快一些。

下面是BookShelfItemTouchHelper的完整代碼:

public class BookShelfItemTouchHelper extends ItemTouchHelper.Callback {
    private final String TAG = "BookShelfItemTouchHelper";
    private List<Book> books;
    private BookshelfAdapter bookshelfAdapter;
    public BookShelfItemTouchHelper(List<Book> books, BookshelfAdapter bookshelfAdapter) {
        this.books = books;
        this.bookshelfAdapter = bookshelfAdapter;
    }
    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        int swipeFlags = 0;//不響應滑動方向
        int flags = makeMovementFlags(dragFlags,swipeFlags);
        return flags;
    }
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        int fromPosition = viewHolder.getAdapterPosition();
        int toPosition = target.getAdapterPosition();
        bookshelfAdapter.notifyItemRangeChanged(Math.min(fromPosition,toPosition),Math.abs(fromPosition - toPosition) + 1);
        if (fromPosition < toPosition){
            for (int i = fromPosition;i<toPosition;i++){
                Collections.swap(books,i,i+1);
            }
        }else {
            for (int i = fromPosition; i > toPosition;i--){
                Collections.swap(books,i,i-1);
            }
        }
        bookshelfAdapter.notifyItemMoved(fromPosition,toPosition);
        return true;
    }
    @Override
    public void onMoved(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, int fromPos, @NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) {
        super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
        bookshelfAdapter.notifyItemRangeChanged(Math.min(fromPos, toPos), Math.abs(fromPos - toPos) + 1);
    }
    /** 選中狀態(tài)改變通知 */
    @Override
    public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
        super.onSelectedChanged(viewHolder, actionState);
        if (actionState == ItemTouchHelper.ACTION_STATE_DRAG){
            int bgColor = viewHolder.itemView.getContext().getResources().getColor(R.color.text_blue);
            viewHolder.itemView.setScaleX(1.2f);
            viewHolder.itemView.setScaleY(1.2f);
            viewHolder.itemView.setBackgroundColor(bgColor);
        }
    }
    /** 手指釋放item或者交互動畫結(jié)束時調(diào)用 viewHolder是釋放的item的ViewHolder對象*/
    @Override
    public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        viewHolder.itemView.setScaleX(1.0f);
        viewHolder.itemView.setScaleY(1.0f);
        int color = viewHolder.itemView.getContext().getResources().getColor(R.color.white);
        viewHolder.itemView.setBackgroundColor(color);
    }
    /** 修改滾動速度 下面是固定了劃動速度*/
    @Override
    public int interpolateOutOfBoundsScroll(@NonNull RecyclerView recyclerView, int viewSize, int viewSizeOutOfBounds, int totalSize, long msSinceStartScroll) {
        final int direction = (int) Math.signum(viewSizeOutOfBounds);
        return 30 * direction;
    }
}

小說刪除

小說刪除相對簡單,是在Adapter中定義了一個方法,當點擊刪除按鈕時會調(diào)用該方法,該方法內(nèi)部時會判斷當刪除數(shù)據(jù)長度大于0時,從Adapter接收的數(shù)據(jù)集里面移除刪除數(shù)據(jù),代碼如下:

/** 刪除選中的數(shù)據(jù) */
fun deleted(){
    if (deletDatas.size&gt;0){
        for (data in deletDatas){
            datas.remove(data)
        }
        deletDatas.clear()
        notifyDataSetChanged()
    }
}

總結(jié)

在實現(xiàn)小說書架功能時,遇到一些需要注意的地方,在此記錄下。
一開始在實現(xiàn)功能時候,將下面的代碼,放到了onMove方法中執(zhí)行,這樣會有一個問題手指拖拽時,手指沒有松開,拖拽就結(jié)束,猜測是因為拖動item時,系統(tǒng)會重繪列表,但下面代碼會重新排序更新位置,就與拖拽產(chǎn)生沖突,導致拖拽結(jié)束。

bookshelfAdapter.notifyItemRangeChanged(Math.min(fromPos, toPos), Math.abs(fromPos - toPos) + 1);

另一個地方是,我想通過ItemDecoration給ReyclerView添加裝飾時,在onDrawOver方法給列表每行開頭小說添加裝飾后,在拖動時候發(fā)現(xiàn),不是開頭的小說也會出現(xiàn)這個效果,onDarwOver方法如下:

public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
    super.onDrawOver(c, parent, state);
    int childCount = parent.getChildCount();
    for (int i=0;i&lt;childCount;i++){
        View child = parent.getChildAt(i);
        if (child!=null &amp;&amp; i%row==0){
            int startX = (child.getLeft()+child.getRight())/2 - decorationBmp.getWidth()/2;
            int startY = child.getTop() + child.getPaddingTop() - decorationBmp.getHeight()/2;
            c.drawBitmap(decorationBmp,startX,startY,paint);
        }
    }
}

拖拽時效果圖如下所示:

查閱資料時,沒有找到解決辦法,只找到拖拽時,會多次調(diào)用ItemDecoration的onDrawOver方法,目前只在拖拽的時候盡量不使用ItemDecoration。

項目代碼地址 github。

以上就是Android自定義控件之小說書架的詳細內(nèi)容,更多關于Android自定義控件小說書架的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解Android應用中preference首選項的編寫方法

    詳解Android應用中preference首選項的編寫方法

    這篇文章主要介紹了Android應用中preference首選項的編寫方法,或許Apple將其翻譯為'偏好設置'更直觀些,即用戶對應用的一些個性化調(diào)整菜單,需要的朋友可以參考下
    2016-04-04
  • Android Binder進程間通信工具AIDL使用示例深入分析

    Android Binder進程間通信工具AIDL使用示例深入分析

    Binder作為Android 眾多的IPC通訊手段之一,在Framework的數(shù)據(jù)傳輸中起到極為關鍵的作用。Binder機制可謂是Android 知識體系里的重中之重,作為偏底層的基礎組件,平時我們很少關注它,而它卻是無處不在,也是Android 面試易考察的點之一
    2022-11-11
  • 簡單實現(xiàn)Android計算器功能

    簡單實現(xiàn)Android計算器功能

    這篇文章主要為大家詳細介紹了自己動手實現(xiàn)的Android計算器功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android 自定義星評空間示例代碼

    Android 自定義星評空間示例代碼

    這篇文章主要介紹了Android 自定義星評空間的實例代碼 ,需要的朋友可以參考下
    2017-06-06
  • Android手勢操作識別詳解

    Android手勢操作識別詳解

    這篇文章主要為大家詳細介紹了Android手勢操作識別,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Android開發(fā)實現(xiàn)長按返回鍵彈出關機框功能

    Android開發(fā)實現(xiàn)長按返回鍵彈出關機框功能

    這篇文章主要介紹了Android開發(fā)實現(xiàn)長按返回鍵彈出關機框功能,涉及Android針對長按事件的響應與處理相關操作技巧,需要的朋友可以參考下
    2017-09-09
  • Android?使用flow實現(xiàn)倒計時的方式

    Android?使用flow實現(xiàn)倒計時的方式

    這篇文章主要介紹了Android?使用flow實現(xiàn)倒計時的方式,借助Flow這個工具,更加優(yōu)雅地實現(xiàn)這個需求功能,文末給大家整理了Android?實現(xiàn)倒計時的幾種方式,需要的朋友可以參考下
    2022-04-04
  • Android編程實現(xiàn)播放MP3功能示例

    Android編程實現(xiàn)播放MP3功能示例

    這篇文章主要介紹了Android編程實現(xiàn)播放MP3功能,結(jié)合實例形式分析了Android播放MP3功能的界面布局與功能實現(xiàn)相關操作技巧,需要的朋友可以參考下
    2017-02-02
  • Android界面刷新的方法分享

    Android界面刷新的方法分享

    Android界面刷新的方法分享,需要的朋友可以參考一下
    2013-05-05
  • Android Studio報:“Attribute application@theme or @ icon ”問題的解決

    Android Studio報:“Attribute application@theme or @ icon ”問題的解

    這篇文章主要給大家介紹了關于Android Studio報:“Attribute application@theme or @ icon ”問題的解決方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧。
    2017-12-12

最新評論