Android kotlin 实现频道管理功能

一、实现效果

二、引入依赖

appbuild.gradle在添加以下代码
1、implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6',这个里面带的适配器,直接调用就即可

BaseRecyclerViewAdapterHelper简称BRVAH

Android SDK是否支持BaseRecyclerViewAdapterHelper:3.0.6
android compileSdkVersion 29
android compileSdkVersion 30
android compileSdkVersion 31
android compileSdkVersion 32
android compileSdkVersion 33

这依赖包还需要得到要添加,在Projectbuild.gradle在添加以下代码,不添加就不行

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }//加上
    }
}

2、AnyLayer:implementation "com.github.goweii:AnyLayer:4.1.4-androidx"

三、源码实现

1、实体类

MySection.java

package com.example.myapplication3.entity;

import com.chad.library.adapter.base.entity.JSectionEntity;

public class MySection extends JSectionEntity {

    private boolean isHeader;
    private int headerNum;
    private Object object;

    private boolean isRecommend;

    public MySection(boolean isHeader, int headerNum, Object object,boolean isRecommend) {
        this.isHeader = isHeader;
        this.headerNum = headerNum;
        this.object = object;
        this.isRecommend = isRecommend;
    }

    public Object getObject() {
        return object;
    }

    @Override
    public boolean isHeader() {
        return isHeader;
    }

    public int getHeaderNum() {
        return headerNum;
    }

    public boolean isRecommend() {
        return isRecommend;
    }

    public void setRecommend(boolean recommend) {
        isRecommend = recommend;
    }
}

2、适配器

SectionQuickAdapter.kt

package com.example.myapplication3.adapter

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.graphics.Color
import android.text.Html
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.chad.library.adapter.base.BaseSectionQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.entity.MySection
import kotlinx.android.synthetic.main.def_section_head.view.*
import java.util.*

class SectionQuickAdapter(layoutResId: Int, sectionHeadResId: Int, data: MutableList<MySection>) :
    BaseSectionQuickAdapter<MySection, BaseViewHolder>(sectionHeadResId, data) {
    init {
        setNormalLayout(layoutResId)
        addChildClickViewIds(R.id.edit)
    }

    var selectedSize: Int = 0             //已选
    var fixSize: Int = 0                 //固定频道数目
    var isRecommend: Boolean = true      //当前是否显示推荐频道
    var mLeft: Int = -1                  //推荐频道蓝色线条距离屏幕左边的距离
    var mRight: Int = -1                 //城市频道蓝色线条距离屏幕左边的距离
    var mTabY: Int = 0                   //tab距离parent的Y的距离

//    var onItemRangeChangeListener: SectionQuickAdapter.OnItemRangeChangeListener? = null

    override fun convertHeader(helper: BaseViewHolder, item: MySection) {
        helper.itemView.run {
            when (item.headerNum) {
                1 -> {
                    header.text = "我最喜欢 "
//                    enter.text = Html.fromHtml("<font size=2 color='#DCDCDC'>按住拖动可以排序</font>")
                }
                2 -> {
                    header.text = Html.fromHtml("全部频道 <font color=\"#DCDCDC\">点击添加频道</font>")
                    edit.visibility = View.GONE
                }
            }
        }
    }

    override fun convert(holder: BaseViewHolder, item: MySection) {
        setChannel(holder, holder.adapterPosition, item)
    }

    private fun setChannel(holder: BaseViewHolder, position: Int, item: MySection) {
        var name = holder.getView<TextView>(R.id.item_textView)
        var delete = holder.getView<ImageView>(R.id.delete)
        var add = holder.getView<TextView>(R.id.tv_add)
        name.text = item.`object` as String
        name.setOnClickListener {
            if (holder.layoutPosition < selectedSize + 1) {
                //tab上面的 点击移除
                if (holder.layoutPosition > fixSize) {
                    removeFromSelected(holder)
                }
            } else {
                //tab下面的 点击添加到已选频道
                selectedSize++
                itemMove(holder.layoutPosition, selectedSize)
                notifyItemChanged(selectedSize)
                //刷新itemDecoration
//                onItemRangeChangeListener?.let { onItemRangeChangeListener!!.refreshItemDecoration() }
            }
        }
        name.setOnLongClickListener {
            true
        }

        delete.setOnClickListener { removeFromSelected(holder) }
        //tab下面及固定频道不显示删除按钮
        if (position - 1 < fixSize || position > selectedSize) {

            //************************新代码**********************
            //固定频道的文字灰色
            if (fixSize == position) {
                name.setTextColor(Color.GRAY)
            } else {
                add.visibility = View.VISIBLE
            }
            //****************************************************

            delete.visibility = View.GONE
        } else {
            delete.visibility = View.VISIBLE

            //************************新代码**********************
            add.visibility = View.GONE
            //****************************************************
        }
    }

//    private fun setTab(holder: ChannelAdapter.TabHolder) {
//        holder.itemView.viewTreeObserver.addOnPreDrawListener(object :
//            ViewTreeObserver.OnPreDrawListener {
//            override fun onPreDraw(): Boolean {
//                mTabY = holder.itemView.top
//                return true
//            }
//
//        })
//    }

    private fun removeFromSelected(holder: BaseViewHolder) {
        val delete = holder.getView<ImageView>(R.id.delete)

        //************************新代码**********************
        val add = holder.getView<TextView>(R.id.tv_add)
        add.visibility = View.VISIBLE
        //****************************************************

        delete.visibility = View.GONE
        val position = holder.layoutPosition
        val bean = data[position]

        if ((isRecommend && bean.isRecommend) || (!isRecommend && !bean.isRecommend)) {
            //移除的频道属于当前tab显示的频道,直接调用系统方法移除
            itemMove(position, selectedSize + 1)
            notifyItemRangeChanged(selectedSize + 1, 1)
            //刷新itemDecoration
//            onItemRangeChangeListener?.let { onItemRangeChangeListener!!.refreshItemDecoration() }
        } else {
            //不属于当前tab显示的频道
            removeAnimation(
                holder.itemView,
                (if (isRecommend) mRight else mLeft).toFloat(),
                mTabY.toFloat(),
                position
            )
        }
        selectedSize--
    }

    private fun removeAnimation(view: View, x: Float, y: Float, position: Int) {
        val fromX = view.left
        val fromY = view.top
        val animatorX = ObjectAnimator.ofFloat(view, "translationX", 0f, x - fromX)
        val animatorY = ObjectAnimator.ofFloat(view, "translationY", 0f, y - fromY)
        val alpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f)
        val set = AnimatorSet()
        set.playTogether(animatorX, animatorY, alpha)
        set.duration = 350
        set.addListener(object : Animator.AnimatorListener {
            override fun onAnimationRepeat(animation: Animator?) {
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationStart(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                data.add(0, data[position])
                data.removeAt(position)
                notifyItemRemoved(position)
//                onItemRangeChangeListener?.let { onItemRangeChangeListener!!.refreshItemDecoration() }
                //这里需要重置view的属性
                resetView(view, x - fromX, y - fromY)
            }
        })
        set.start()
    }

    private fun resetView(view: View, toX: Float, toY: Float) {
        val animatorX = ObjectAnimator.ofFloat(view, "translationX", -toX, 0f)
        val animatorY = ObjectAnimator.ofFloat(view, "translationY", -toY, 0f)
        val alpha = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f)
        val set = AnimatorSet()
        set.playTogether(animatorX, animatorY, alpha)
        set.duration = 0
        set.startDelay = 5
        set.start()
    }

    fun itemMove(fromPosition: Int, toPosition: Int) {

        if (fromPosition < toPosition) {
            for (i in fromPosition until toPosition) {
                Collections.swap(data, i, i + 1)
            }
        } else {
            for (i in fromPosition downTo toPosition + 1) {
                Collections.swap(data, i, i - 1)
            }
        }
        notifyItemMoved(fromPosition, toPosition)
    }
}

3、拖拽事件(ItemTouchHelper.Callback())

item拖拽,文件DragTouchHelper.kt

package com.example.myapplication3.widget

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.DashPathEffect
import android.graphics.Paint
import android.graphics.drawable.GradientDrawable
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter.base.dragswipe.DragAndSwipeCallback
import com.chad.library.adapter.base.module.BaseDraggableModule
import com.example.myapplication3.R
import com.example.myapplication3.past.ChannelRvAdapter1
import com.example.myapplication3.past.DragAdapter
import com.example.myapplication3.adapter.SectionQuickAdapter
import com.example.myapplication3.entity.MySection
import java.util.*

/**
 * GitHub : https://github.com/yechaoa
 * CSDN : http://blog.csdn.net/yechaoa
 *
 * Created by yechao on 2022/7/17.
 * Describe :
 */

class ItemDragCallback2(var mAdapter: SectionQuickAdapter, var mPadding: Int) : ItemTouchHelper.Callback()
{
    private val mPaint: Paint = Paint()

    init {
        mPaint.color = Color.GRAY
        mPaint.isAntiAlias = true
        mPaint.strokeWidth = 1f
        mPaint.style = Paint.Style.STROKE
        val pathEffect = DashPathEffect(FloatArray(2, { 5f }), 5f)
        mPaint.pathEffect = pathEffect
    }

    override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
        //固定位置及tab下面的channel不能拖动
        val position = viewHolder!!.layoutPosition
        if (position < mAdapter.fixSize + 1 || position > mAdapter.selectedSize) {
            return makeMovementFlags(0, 0)
        }
        val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
        return makeMovementFlags(dragFlags, 0)
    }

    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
        val fromPosition = viewHolder!!.layoutPosition    //拖动的位置
        val toPosition = target!!.layoutPosition         //释放的位置
        //固定位置及tab下面的channel不能移动
        if (toPosition < mAdapter.fixSize + 1 || toPosition > mAdapter.selectedSize) {
            return false
        }
        mAdapter.itemMove(fromPosition, toPosition)
        return true
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        //滑动重写这里
    }

    override fun onChildDrawOver(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder?, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
        super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
//        if (dX != 0f && dY != 0f || isCurrentlyActive) {
//            //长按拖拽时底部绘制一个虚线矩形
//            c!!.drawRect(viewHolder!!.itemView.left.toFloat(), (viewHolder.itemView.top - mPadding).toFloat(), viewHolder.itemView.right.toFloat(), viewHolder.itemView.bottom.toFloat(), mPaint)
//        }
    }

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
        super.onSelectedChanged(viewHolder, actionState)
        if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
            //长按时调用 设置颜色 阴影
//            val holder = viewHolder as ChannelAdapter.ChannelHolder
//            holder.name.setBackgroundColor(Color.parseColor("#FDFDFE"))
//            holder.delete.visibility= View.GONE
//            holder.name.elevation=5f
            //*******新代码********
            super.onSelectedChanged(viewHolder, actionState)
            //*******新代码********
        }
    }

    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        super.clearView(recyclerView, viewHolder)
        //重置view
//        val holder=viewHolder as ChannelAdapter.ChannelHolder
//        holder.name.setBackgroundColor(Color.parseColor("#f0f0f0"))
//        holder.delete.visibility= View.VISIBLE
//        holder.name.elevation=0f
        //*******新代码********
        super.clearView(recyclerView, viewHolder)
        //*******新代码********

    }
}

4、视图实现

ChannelActivity.kt

package com.example.myapplication3.channel

import android.os.Bundle
import android.view.Gravity
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication3.R
import com.example.myapplication3.adapter.SectionQuickAdapter
import com.example.myapplication3.entity.MySection
import com.example.myapplication3.widget.ItemDragCallback2
import kotlinx.android.synthetic.main.activity_channel.*
import per.goweii.anylayer.AnyLayer
import per.goweii.anylayer.dialog.DialogLayer
import per.goweii.anylayer.dialog.DialogLayer.OutsideTouchedListener
import per.goweii.anylayer.widget.SwipeLayout

class ChannelActivity : AppCompatActivity()
//    , SectionQuickAdapter.OnItemRangeChangeListener
{

    private var mRecyclerView: RecyclerView? = null

    companion object {
        private var SPAN_COUNT = 4
    }

    private var list: MutableList<MySection> = ArrayList()
    private var itemTouchHelper: ItemTouchHelper? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_channel)
        button.setOnClickListener {
            showRadListDialog(initData())
        }
    }

    private fun showRadListDialog(mList: MutableList<MySection>) {
        val rvDialog = AnyLayer.dialog()
            .contentView(R.layout.activity_section_uer)
            .backgroundDimDefault()
            .gravity(Gravity.BOTTOM)
            .swipeDismiss(SwipeLayout.Direction.BOTTOM)
            .animStyle(DialogLayer.AnimStyle.BOTTOM)
            .backgroundDimAmount(0.5F)//背景变暗的程度0~1,直接调用到这函数里看文档就即可
        rvDialog.outsideTouched(OutsideTouchedListener {
            mList.clear()
        })
        rvDialog.show()
        mRecyclerView = rvDialog.getView<RecyclerView>(R.id.rv_list)
        mRecyclerView?.layoutManager = GridLayoutManager(this, SPAN_COUNT)
        val mAdapter = SectionQuickAdapter(R.layout.item_drag_grid, R.layout.def_section_head, mList)
//        val animator = DefaultItemAnimator()
//        animator.moveDuration = 400      //设置动画时间
//        animator.removeDuration = 0
//        mRecyclerView?.itemAnimator = animator
        mRecyclerView?.adapter = mAdapter
        mAdapter.fixSize = 1
        mAdapter.selectedSize = 10 //点击进入频道下面的频道数
//        mAdapter.onItemRangeChangeListener = this
        // 设置拖拽
        val dragCallBack = ItemDragCallback2(mAdapter,2)
        itemTouchHelper = ItemTouchHelper(dragCallBack)
        itemTouchHelper!!.attachToRecyclerView(mRecyclerView)
    }

    private fun initData(): MutableList<MySection> {
        list.add(MySection(true, 1, "我最喜欢 点击进入频道", false))
        list.add(MySection(false, 0, "测试1", true))
        list.add(MySection(false, 0, "测试2", true))
        list.add(MySection(false, 0, "测试3", true))
        list.add(MySection(false, 0, "测试4", true))
        list.add(MySection(false, 0,"测试5",true))
        list.add(MySection(false, 0,"测试6",true))
        list.add(MySection(false, 0,"测试7",true))
        list.add(MySection(false, 0,"测试8",true))
        list.add(MySection(false, 0,"测试9",true))
        list.add(MySection(false, 0,"测试10",true))

        list.add(MySection(true, 2, "全部频道 点击添加频道", false))
        list.add(MySection(false, 0, "测试11", true))
        list.add(MySection(false, 0, "测试12", true))
        list.add(MySection(false, 0, "测试13", true))
        list.add(MySection(false, 0, "测试14", true))
        list.add(MySection(false, 0,"测试15",true))
        list.add(MySection(false, 0,"测试16",true))
        list.add(MySection(false, 0,"测试17",true))
        list.add(MySection(false, 0,"测试18",true))
        list.add(MySection(false, 0,"测试19",true))
        list.add(MySection(false, 0,"测试20",true))
        return list
    }

//    override fun refreshItemDecoration() {
//        mRecyclerView?.invalidateItemDecorations()
//    }
}

activity_section_uer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="700dp"
    android:background="@color/white">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

item_drag_grid.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="75dp"
    android:layout_height="50dp">

    <TextView
        android:id="@+id/item_textView"
        android:layout_width="60dp"
        android:layout_height="30dp"
        android:layout_centerInParent="true"
        android:background="@drawable/shape_radius5_green"
        android:gravity="center"
        android:text="测试"
        android:textColor="@color/black"
        android:textSize="13dp"/>

    <ImageView
        android:id="@+id/delete"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_alignParentRight="true"
        android:src="@mipmap/delete"
        android:visibility="visible"/>

    <TextView
        android:id="@+id/tv_add"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_alignRight="@id/item_textView"
        android:layout_alignParentRight="true"
        android:layout_marginTop="8dp"
        android:text="+"
        android:visibility="gone"/>
</RelativeLayout>

在这里插入图片描述
shape_radius5_green.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/bg" />
    <corners android:radius="5dp" />
</shape>
<color name="bg">#E7E7E7</color>

def_section_head.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:padding="10dp">

    <TextView
        android:id="@+id/header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:text="已选频道 "
        android:textStyle="bold"/>

<!--    <TextView-->
<!--        android:id="@+id/enter"-->
<!--        android:layout_width="wrap_content"-->
<!--        android:layout_height="wrap_content"-->
<!--        android:layout_toRightOf="@id/header"-->
<!--        android:text="按住拖动可以排序"/>-->

    <TextView
        android:id="@+id/edit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:textColor="@color/red"
        android:text="按住拖动可以排序" />
</RelativeLayout>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Android Kotlin实现个人热点功能很简单,可以按照以下步骤进行操作: 1. 在AndroidManifest.xml文件中添加以下权限: ``` <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> ``` 2. 创建一个WifiManager对象,并使用以下代码开启Wifi热点: ``` val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager wifiManager.isWifiEnabled = false //关闭Wifi连接 val wifiConfiguration = WifiConfiguration() wifiConfiguration.SSID = "YOUR_SSID" //设置热点名称 wifiConfiguration.preSharedKey = "YOUR_PASSWORD" //设置热点密码 wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED) //设置加密方式 wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK) //设置加密方式 wifiManager.addNetwork(wifiConfiguration) //添加网络配置 val apMethod = wifiManager.javaClass.getMethod("setWifiApEnabled", WifiConfiguration::class.java, Boolean::class.java) //反射获取setWifiApEnabled方法 apMethod.invoke(wifiManager, wifiConfiguration, true) //开启热点 ``` 3. 如果想关闭热点,可以使用以下代码: ``` wifiManager.isWifiEnabled = true //开启Wifi连接 val apMethod = wifiManager.javaClass.getMethod("setWifiApEnabled", WifiConfiguration::class.java, Boolean::class.java) //反射获取setWifiApEnabled方法 apMethod.invoke(wifiManager, null, false) //关闭热点 ``` 注意:在Android 9.0及以上版本中,Google限制了开启热点的权限,需要在设备的开发者选项中打开“打开设置时询问每个应用”的选项,并在应用中请求用户授权才能开启热点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬sir哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值