oligazar
6/25/2017 - 9:05 AM

RecyclerView starting point

// to avoid scrolling to recyclerview inside nested scroll view use this in the view above it
                android:focusableInTouchMode="true"
class VerticalSpaceItemDecoration(vSpaceDip: Int,
                                  headerDip: Int = -1,
                                  footerDip: Int = -1,
                                  val isDip: Boolean = true) : RecyclerView.ItemDecoration() {

    lateinit var resources: Resources
    private val header = if (headerDip == -1) vSpaceDip else headerDip
    private val footer = if (footerDip == -1) vSpaceDip else footerDip
    private val mVerticalSpaceHeight: Int by lazy { if (isDip) dp(vSpaceDip, resources) else vSpaceDip }
    private val mHeaderHeight: Int by lazy { if (isDip) dp(header, resources) else header }
    private val mFooterHeight: Int by lazy { if (isDip) dp(footer, resources) else footer }

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
        resources = view.context.resources
        when {
            parent.getChildAdapterPosition(view) == 0 -> {
                // vertical spaces for the first element
                outRect.top = mHeaderHeight
                outRect.bottom = mVerticalSpaceHeight
                // vertical spaces for the last element
            }
            parent.getChildAdapterPosition(view) == parent.adapter.itemCount - 1 -> outRect.bottom = mFooterHeight
            else -> // vertical spaces for other elements
                outRect.bottom = mVerticalSpaceHeight
        }
    }
}


class HorizontalSpaceItemDecoration(vSpaceDip: Int,
                                  headerDip: Int = -1,
                                  footerDip: Int = -1,
                                  val isDip: Boolean = true) : RecyclerView.ItemDecoration() {

    lateinit var resources: Resources
    private val header = if (headerDip == -1) vSpaceDip else headerDip
    private val footer = if (footerDip == -1) vSpaceDip else footerDip
    private val mVerticalSpaceHeight: Int by lazy { if (isDip) dp(vSpaceDip, resources) else vSpaceDip }
    private val mHeaderHeight: Int by lazy { if (isDip) dp(header, resources) else header }
    private val mFooterHeight: Int by lazy { if (isDip) dp(footer, resources) else footer }

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
        resources = view.context.resources
        when {
            parent.getChildAdapterPosition(view) == 0 -> {
                // vertical spaces for the first element
                outRect.left = mHeaderHeight
                outRect.right = mVerticalSpaceHeight
                // vertical spaces for the last element
            }
            parent.getChildAdapterPosition(view) == parent.adapter.itemCount - 1 -> outRect.right = mFooterHeight
            else -> // vertical spaces for other elements
                outRect.right = mVerticalSpaceHeight
        }
    }
}

// divider in Monte app for comments (line with wome left gap)
class CommentItemDecoration(private val verticalSpaceHeight: Int,
                            private val headerHeight: Int,
                            private val footerHeight: Int) : RecyclerView.ItemDecoration() {
    
    private var mDivider: Drawable? = null

    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {

        val resources = parent.resources
        val left = resources.dp(60)
        val right = parent.width - parent.paddingRight
        mDivider = ContextCompat.getDrawable(parent.context, R.drawable.comment_divider)

        val childCount = parent.childCount
        for (i in 0 until childCount) {

            val child = parent.getChildAt(i)
            var top: Int
            var bottom: Int
            val params = child.layoutParams as RecyclerView.LayoutParams

            if (i == 0) {
                top = child.top - params.topMargin
                bottom = top + mDivider!!.intrinsicHeight
                drawDivider(c, parent.paddingLeft, top, right, bottom)
            }

            top = child.bottom + params.bottomMargin
            bottom = top + mDivider!!.intrinsicHeight

            drawDivider(c, left, top, right, bottom)
        }
    }

    private fun drawDivider(c: Canvas, left: Int, top: Int, right: Int, bottom: Int) {
        mDivider!!.setBounds(left, top, right, bottom)
        mDivider!!.draw(c)
    }

    //    @Override
    //    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
    //                               RecyclerView.State state) {
    //        Resources resources = view.getResources();
    //        if (parent.getChildAdapterPosition(view) == 0) { // vertical spaces for the first element
    //            outRect.top = dipToPixels(headerHeight, resources);
    //            outRect.bottom = dipToPixels(verticalSpaceHeight, resources);
    //            // vertical spaces for the last element
    //        } else if (parent.getChildAdapterPosition(view) == parent.getAdapter().getItemCount() - 1){
    //            outRect.bottom = dipToPixels(footerHeight, resources);
    //        } else { // vertical spaces for other elements
    //            outRect.bottom = dipToPixels(verticalSpaceHeight, resources);
    //        }
    //    }

    fun Resources.dp(dp: Int) = Math.round(dp * displayMetrics.density)
}

tools:listitem="@layout/cell_feed"

tools:showIn="@layout/content_feed"


    private fun RecyclerView.enableDragging() {

        val callback = object: ItemTouchHelper.Callback() {

            override fun getMovementFlags(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?): Int {
                val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
                val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END
                return makeMovementFlags(dragFlags, swipeFlags)
            }

            override fun onMove(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {

                mAdapter.onItemMove(viewHolder.adapterPosition, target.adapterPosition)
                return true
            }

            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                mAdapter.onItemDismiss(viewHolder.adapterPosition)
            }

            override fun isLongPressDragEnabled() = true
            override fun isItemViewSwipeEnabled() = true
        }
        val touchHelper = ItemTouchHelper(callback)
        touchHelper.attachToRecyclerView(this)
    }
interface ItemTouchHelperAdapter {

    // drag'n'drop in firebase: https://groups.google.com/forum/#!topic/firebase-talk/UUocZUZJlRU
    // and https://stackoverflow.com/questions/38135102/how-to-reorder-the-data-from-firebase-real-time-database
    // and fresh one: https://stackoverflow.com/questions/46138183/drag-and-drop-in-recyclerview-using-firebase
    // in recyclerview with handler: https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-6a6f0c422efd
    
    fun onItemMove(fromPosition: Int, toPosition: Int): Boolean
    
    fun onItemDismiss(position: Int)
}
    
  // in recycler adapter which implements TouchHelperAdapter interface
  
  override fun onItemDismiss(position: Int) {
        categories.removeAt(position)
        notifyItemRemoved(position)
    }

    override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
        if (fromPosition < toPosition) {
            for (i in fromPosition until toPosition) {
                Collections.swap(categories, i, i + 1)
            }
        } else {
            for (i in fromPosition downTo toPosition + 1) {
                Collections.swap(categories, i, i - 1)
            }
        }
        notifyItemMoved(fromPosition, toPosition)
        return true
    }
public static class ViewHolder extends RecyclerView.ViewHolder implements OnCreateContextMenuListener {
TextView tvTitle;
ImageView ivImage;
    public ViewHolder(View v) {
        super(v);
        tvTitle =(TextView)v.findViewById(R.id.item_title);
        v.setOnCreateContextMenuListener(this);


    }
    
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) {

        menu.setHeaderTitle("Select The Action");    
        menu.add(0, v.getId(), 0, "Call");//groupId, itemId, order, title   
        menu.add(0, v.getId(), 0, "SMS"); 

    }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  super.onViewCreated(view, savedInstanceState)
  
  //...

    recyclerView.adapter = playerAdapter
    recyclerView.layoutManager = LinearLayoutManager(activity)
    recyclerView.setHasFixedSize(true)
    recyclerView.addItemDecoration(VerticalItemDecoration(16f))
}


class PlayerAdapter(val onItemClick: (Int) -> Unit) : RealmRecyclerViewAdapter<PlayerAdapter.PlayerVH, BookFile>() {

    var selectedItemPosition = 0

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): PlayerVH {
        val itemView = LayoutInflater.from(parent?.context).inflate(R.layout.item_book_file, parent, false)
        val holder = PlayerVH(itemView)
        return holder
    }

    override fun onBindViewHolder(holder: PlayerVH, position: Int) {
        val file = getItem(position)
        holder.title.text = file.description
        Log.d("PlayerFragment","bookFiles, onBindViewHolder, position:$position, description:${file.description}")
        holder.itemView.isSelected = selectedItemPosition == position
        holder.itemView.setOnClickListener {

            val oldPosition = selectedItemPosition
            selectedItemPosition = position
            notifyItemChanged(oldPosition)
            notifyItemChanged(selectedItemPosition)

            onItemClick(position)
        }
    }

    class PlayerVH(view: View) : RecyclerView.ViewHolder(view) {
        val title = view.findViewById(R.id.title) as TextView
    }
}