I am struggling with removing PASTE option. Although i am able to remove PASTE option from menu while selecting text from edtittext but in some devices instead of Paste, Clipboard option is visible. Can anyone suggest any workaround ?
#Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
Log.e("TAG","====="+ element.getMethodName()+ "====");
if (element.getMethodName().equals("canPaste") || element.equals("canSuggest")) {
return -1;
}
}
return super.getSelectionStart();
}
You can remove all types of copy paste from EditText by using this kotlin extension function:
fun EditText.disableCopyPaste() {
this.customInsertionActionModeCallback= object : ActionMode.Callback{
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return false
}
override fun onDestroyActionMode(mode: ActionMode?) {
}
}
this.customSelectionActionModeCallback = object : ActionMode.Callback{
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return false
}
override fun onDestroyActionMode(mode: ActionMode?) {
}
}
this.isLongClickable = false
this.setTextIsSelectable(false)
this.addTextChangedListener( object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
if (after - count > 1) {
this#disableCopyPaste.setText(s)
this#disableCopyPaste.setSelection(s.toString().length)
}
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
}
})
}
Link reference: https://gist.github.com/SanikaVanjari/83758a53c9d52012e034e855c4f8653e
Related
I want hide option Paste when click double or Long Click Edittext
enter image description here
I tried:
edtSetName.customSelectionActionModeCallback = object : ActionMode.Callback {
override fun onCreateActionMode(p0: ActionMode?, p1: Menu?): Boolean {
return true
}
override fun onPrepareActionMode(p0: ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onActionItemClicked(p0: ActionMode?, p1: MenuItem?): Boolean {
return false
}
override fun onDestroyActionMode(p0: ActionMode?) {}
}
But that hide all option
I don't find a way to hide the menu popup, But you can disable it from pasting if the user taps on the menu
Create a custom EditText and override the onTextContextMenuItem method and return false for android.R.id.paste and android.R.id.pasteAsPlainText menu id's
#Override
public boolean onTextContextMenuItem(int id) {
switch (id){
case android.R.id.paste:
case android.R.id.pasteAsPlainText:
return false;
}
return super.onTextContextMenuItem(id);
}
On text selection, I do not want the user to see the Call option when they try to select a number from the TextView.
Is there a way to disable the call intent itself for the app?
I tried below, but I could not find the call option in the Menu to remove it.
fun TextView.disableCall() {
setCustomSelectionActionModeCallback(
object : ActionMode.Callback {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?) = false
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
menu?.apply {
//Could not find the call option menu to remove
removeItem(android.R.id.copy)
removeItem(android.R.id.cut)
}
return true
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
override fun onDestroyActionMode(mode: ActionMode?) {
// no-op
}
}
)
}
I was following along the Android Room With a View tutorial.
The tutorial makes use of DiffUtil to compute changes in the list and update the RecyclerView accordingly.
However, when removing or adding items to the RecyclerView, DiffUtil always causes the entire RecyclerView to reload, instead of calling the correct notifyItemRemoved or notifyItemInserted.
My Adapter:
class MarksAdapter(private val context: Context) :
ListAdapter<Mark, MarksAdapter.MarkViewHolder>(MarksComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MarkViewHolder {
return MarkViewHolder.create(parent)
}
override fun onBindViewHolder(holder: MarkViewHolder, position: Int) {
val mark = getItem(position)
holder.bind(context, mark)
}
class MarkViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private var mark: Mark? = null
fun bind(context: Context, mark: Mark) {
this.mark = mark
// Removed for brevity...
}
companion object {
fun create(parent: ViewGroup): MarkViewHolder {
val view: View =
LayoutInflater.from(parent.context).inflate(R.layout.card_view, parent, false)
return MarkViewHolder(view)
}
}
}
class MarksComparator : DiffUtil.ItemCallback<Mark>() {
override fun areItemsTheSame(oldItem: Mark, newItem: Mark): Boolean {
return oldItem === newItem
}
override fun areContentsTheSame(oldItem: Mark, newItem: Mark): Boolean {
return oldItem == newItem
}
}
}
From the activity/fragment:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerViewMarks.apply {
marksAdapter = MarksAdapter(context)
adapter = marksAdapter
layoutManager = LinearLayoutManager(this#MarksOverviewFragment.requireContext())
}
marksViewModel.allMarks.observe(viewLifecycleOwner) { marks ->
marks?.let { marksAdapter.submitList(it) }
}
}
After thinking about it some more, the only place where I can actually influence what DiffUtil does, is within the DiffUtil.Callback.
So after changing:
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return newList[newItemPosition] === oldList[oldItemPosition]
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return newList[newItemPosition] == oldList[oldItemPosition]
}
to:
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return newList[newItemPosition].Uid == oldList[oldItemPosition].Uid
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return newList[newItemPosition] == oldList[oldItemPosition]
}
(notice the comparison of Uid instead of identity)
...the DiffUtil works as expected.
What I'm not sure however, is why it worked in the tutorial, but not for me.
My textchanged listener is for updatestockdetail() is working very weirdly, it crashes after 4-5 times changing the text and it also shows the first item when i change the text for the third time. I believe i am ding something majorly wrong. If somebody could help me, would be very glad.
class RecyclerViewAdapterU (val dataList:ArrayList<ModelClass>): RecyclerView.Adapter<RecyclerViewAdapterU.ViewHolder>() {
var _binding: UploadItemViewBinding? = null
val binding get() = _binding!!
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RecyclerViewAdapterU.ViewHolder {
val v =
LayoutInflater.from(parent.context).inflate(R.layout.upload_item_view, parent, false)
_binding = UploadItemViewBinding.bind(v)
return ViewHolder(binding.root)
}
fun getUpdatedDetails(skucode:String,pos:Int){
// val skuDetails:ArrayList<ModelClass>
val call: Call<List<ModelClass>>? =
ApiClient.instance?.myApi?.getfromsku(skucode)!!
call!!.enqueue(object : Callback<List<ModelClass>?> {
override fun onResponse(
call: Call<List<ModelClass>?>,
response: Response<List<ModelClass>?>
) {
val skuDetails=response.body()
if (!skuDetails.isNullOrEmpty()) {
val x=dataList[pos].sku_code
for (i in skuDetails.indices){
println(skuDetails[i].sku_code)
println(".........$pos")
if (skuDetails[i].sku_code!=x){
dataList.removeAt(pos)
dataList.add(pos,skuDetails[i])
notifyItemChanged(pos)
}
}
}
}
override fun onFailure(call: Call<List<ModelClass>?>, t: Throwable) {
}
})
}
override fun onBindViewHolder(holder: ViewHolder, #SuppressLint("RecyclerView") position: Int) {
bindItems(dataList[position])
holder.getStock()
holder.updateStockDetail()
}
fun bindItems(data: ModelClass) {
binding.apply {
itemquant.text=data.item_quant
uploadItemName.text = data.item_name
uploadMfg.text = data.mfg
skuStock.setText(data.item_stock.toString())
skuCode.setText(data.sku_code)
}
}
override fun getItemCount(): Int {
return dataList.size
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun getStock() {
binding.skuStock.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
if (binding.skuStock.isFocused){
for (i in 0 until RecyclerViewAdapter.ob.dataSelected.size){
if (editable.toString().trim()!=""){
var x= editable.toString().trim().toInt()
RecyclerViewAdapter.ob.dataSelected[adapterPosition].item_stock=x
//getting current itemstock before pushing update.
//assigning latest itemstock to the data for the update
}
}
}}
})
}
fun updateStockDetail(){
binding.skuCode.addTextChangedListener(object : TextWatcher{
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
}
override fun afterTextChanged(editable: Editable) {
binding.skuCode.removeTextChangedListener(this)
var pos:Int=adapterPosition
var x= editable.toString().trim()
//RecyclerViewAdapter.ob.dataSelected[adapterPosition].sku_code=x
println("$x in textwatcher and $pos")
//getting edited text and calling the function to get updated details.
getUpdatedDetails(x,pos)
binding.skuCode.addTextChangedListener(this)
}
})
}
}
}
Before anyone asks, ob.dataselected comes from another rcv adapter. There is a issue in notifyitemchanged(pos) in getupdateddetails() which is called from updateStockDetail().
binding.skuCode.addTextChangedListener(this)
above code is causing the loop. You have to get rid of this line.
I want to use this callback as a method parameter in my class.
In order to avoid duplication at the moment I'm just declaring it in a local variable but I'm not sure this is a best practice.
What's the best way to achieve this?
private val callback = object : ActionMode.Callback {
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
mode?.menuInflater?.inflate(R.menu.items_contextual_action_bar, menu)
isInActionMode = true
return true
}
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return when (item?.itemId) {
R.id.action_delete -> {
DeleteItemsDialogFragment().show(childFragmentManager, DeleteItemsDialogFragment.TAG.toString())
true
}
else -> false
}
}
override fun onDestroyActionMode(mode: ActionMode?) {
isInActionMode = false
tracker?.clearSelection()
actionMode = null
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean = false
}