亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

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

功能分析

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

代碼實(shí)現(xiàn)

小說的展示

我這里是使用RecyclerView實(shí)現(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實(shí)現(xiàn)

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

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

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

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

onMove:這個(gè)方法是,當(dāng)手指移動(dòng)到某個(gè)item上時(shí),會(huì)觸發(fā)這個(gè)函數(shù)(個(gè)人理解這個(gè)函數(shù)觸發(fā)時(shí)機(jī)是,當(dāng)手指拖拽item在目標(biāo)view上停留了一小會(huì)),這個(gè)方法里面viewHolder參數(shù)是手指拖拽item的ViewHolde,target是目標(biāo)item的ViewHolder。在這里我們是把拖拽item放到目標(biāo)item位置上,并返回true。方法末尾,還需要調(diào)用Adapter的notifyItemMoved()方法,告訴RecyclerView這兩個(gè)item發(fā)生了變換,并重繪。關(guān)于托拽item與目標(biāo)item位置變換,如果我們把拖動(dòng)的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會(huì)觸發(fā)這個(gè)方法,在這個(gè)方法里需要調(diào)用Adapter的notifyItemRangeChanged()方法來批量更新,item位置變換過程中受影響的數(shù)據(jù)。

onSelectedChanged():當(dāng)手指長按選中item時(shí)會(huì)觸發(fā)這個(gè)方法,這個(gè)方法中,我修改了item的背景色并稍微擴(kuò)大item的寬高。

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

interpolateOutOfBoundsScroll:這個(gè)方法是可以設(shè)置滾動(dòng)速度,如果不修改的話,會(huì)發(fā)現(xiàn)拖拽item到頂部或底部時(shí)候,向上或下的速度很慢,在這里設(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)滑動(dò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或者交互動(dòng)畫結(jié)束時(shí)調(diào)用 viewHolder是釋放的item的ViewHolder對(duì)象*/
    @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);
    }
    /** 修改滾動(dòng)速度 下面是固定了劃動(dòng)速度*/
    @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;
    }
}

小說刪除

小說刪除相對(duì)簡單,是在Adapter中定義了一個(gè)方法,當(dāng)點(diǎn)擊刪除按鈕時(shí)會(huì)調(diào)用該方法,該方法內(nèi)部時(shí)會(huì)判斷當(dāng)刪除數(shù)據(jù)長度大于0時(shí),從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é)

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

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

另一個(gè)地方是,我想通過ItemDecoration給ReyclerView添加裝飾時(shí),在onDrawOver方法給列表每行開頭小說添加裝飾后,在拖動(dòng)時(shí)候發(fā)現(xiàn),不是開頭的小說也會(huì)出現(xiàn)這個(gè)效果,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);
        }
    }
}

拖拽時(shí)效果圖如下所示:

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

項(xiàng)目代碼地址 github

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

相關(guān)文章

最新評(píng)論