最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

在手機看小說的時候,看到一個很有意思的效果,在UC瀏覽器切換到小說書架時候,可以在這個界面手指長按一本書拖拽它,當(dāng)拖拽到其他小說后面時候??梢詫⑵渌≌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,設(shè)置代碼如下:

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

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

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

onMove:這個方法是,當(dāng)手指移動到某個item上時,會觸發(fā)這個函數(shù)(個人理解這個函數(shù)觸發(fā)時機是,當(dāng)手指拖拽item在目標(biāo)view上停留了一小會),這個方法里面viewHolder參數(shù)是手指拖拽item的ViewHolde,target是目標(biāo)item的ViewHolder。在這里我們是把拖拽item放到目標(biāo)item位置上,并返回true。方法末尾,還需要調(diào)用Adapter的notifyItemMoved()方法,告訴RecyclerView這兩個item發(fā)生了變換,并重繪。關(guān)于托拽item與目標(biāo)item位置變換,如果我們把拖動的item位置看為fromPosition,把目標(biāo)item的位置看為toPosition。我們需要把拖拽item放到目標(biāo)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():當(dāng)手指長按選中item時會觸發(fā)這個方法,這個方法中,我修改了item的背景色并稍微擴大item的寬高。

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

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

下面是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;//不響應(yīng)滑動方向
        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中定義了一個方法,當(dāng)點擊刪除按鈕時會調(diào)用該方法,該方法內(nèi)部時會判斷當(dāng)刪除數(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)生沖突,導(dǎo)致拖拽結(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)容,更多關(guān)于Android自定義控件小說書架的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

江北区| 潢川县| 双流县| 洛川县| 遂昌县| 丹东市| 博野县| 平罗县| 资源县| 灵武市| 韩城市| 深水埗区| 西盟| 察雅县| 正安县| 恩施市| 成安县| 和顺县| 汕头市| 突泉县| 华蓥市| 锡林浩特市| 茶陵县| 怀宁县| 棋牌| 河西区| 信丰县| 高雄县| 临朐县| 岳普湖县| 莱州市| 咸阳市| 临江市| 疏附县| 调兵山市| 郧西县| 平罗县| 怀来县| 抚松县| 武平县| 沾化县|