Disable paste from clipboard suggestions on EditText - java

To prevent an EditText from receiving content from the clipboard, I disable the long click and text selectable, plus cleared the action mode menu:
EditText editText = findViewById(R.id.et);
editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
editText.setTextIsSelectable(false);
editText.setLongClickable(false);
The problem is that I keep receiving clipboard suggestions that when selected are pasted to my EditText. How can I disable this or simply ignore this pasted content?

To disable all types of copy past from keyboard, keyboard extension, Action Menu and any other type you can add a textChangeListener to your EditText and check in the method beforeTextChanged like the follow:
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
if (after - count > 1) {
editText.setText(s)
editText.setSelection(s.toString().length)
}
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int){}
})
this solution works if someone past more than one character at the time. Good luck

Related

ClickableSpan AND onClickListener on TextView

I need to have both on a TextView:
When the TextView is clicked, trigger a function. But when a certain part of the text is clicked, trigger a different function.
So I have a ClickableSpan for that certain part, and an OnTouchListener on the whole TextView:
SpannableString string = new SpannableString(input);
// ...
string.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
functionOne();
}
}, start, i, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(string);
// ...
textView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
Both work fine for themselves:
If I do not add the OnTouchListener, it calls functionOne(), triggered from the ClickableSpan.
But if I also add the OnTouchListener, it only calls gestureDetector.onTouchEvent(event). Also if I click on the certain part of the text, where the ClickableSpan should be triggered.
How can I have both?
So that if the certain part is clicked, the ClickableSpan is triggered, and if a different part of the text is clicked, then gestureDetector.onTouchEvent(event) is called.
Try this below function to achieve clickable span and there is no need to call touch listener. click event will be handled by ClickableSpan.
fun setClickableSpan(
spannable: Spannable,
paths: ArrayList<String>,
listener: EventListener
) {
for (i in paths.indices) {
val indexOfPath = spannable.toString().indexOf(paths[i])
if (indexOfPath == -1) {
continue
}
val clickableSpan: ClickableSpan = object : ClickableSpan() {
override fun onClick(textView: View) {
listener.onItemClick(textView, i, paths[i])
}
}
spannable.setSpan(
clickableSpan, indexOfPath,
indexOfPath + paths[i].length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}

How to partially disable click on home button in Android toolbar?

I have implemented onOptionsItemSelected to have control over the home button:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
if (mode) {
reset()
}
}
}
return super.onOptionsItemSelected(item)
}
Now, when I press home, I go back to the previous fragment. What I need is, if the mode is true, when I click on home, to trigger ONLY the reset() function without going back to the previous fragment. If it's false, simply go back. How can I achieve this?
You should return true to say the parent that the click on the menu item is consumed.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
if (mode) {
reset()
return true
}
}
}
return super.onOptionsItemSelected(item)
}

Sliding Up Panel (Java to Kotlin)

How can I display panel states of SlidingUpPanel in Kotlin?
I want to use https://github.com/umano/AndroidSlidingUpPanel library, following this tutorial:
http://www.devexchanges.info/2015/05/making-sliding-up-panel-like-google.html
and the result should look like this:
https://www.youtube.com/watch?v=g464fp-2dQU
The code in Java from tutorial link:
private SlidingUpPanelLayout.PanelSlideListener onSlideListener() {
return new SlidingUpPanelLayout.PanelSlideListener() {
#Override
public void onPanelSlide(View view, float v) {
textView.setText("panel is sliding");
}
#Override
public void onPanelCollapsed(View view) {
textView.setText("panel Collapse");
}
#Override
public void onPanelExpanded(View view) {
textView.setText("panel expand");
}
#Override
public void onPanelAnchored(View view) {
textView.setText("panel anchored");
}
#Override
public void onPanelHidden(View view) {
textView.setText("panel is Hidden");
}
};
}
The converted code from Java to Kotlin (I put toast from anko library instead of textView):
private fun onSlideListener(): SlidingUpPanelLayout.PanelSlideListener {
return object : SlidingUpPanelLayout.PanelSlideListener {
override fun onPanelSlide(view: View, v: Float) {
toast("panel is sliding")
}
override fun onPanelCollapsed(view: View) {
toast("panel Collapse")
}
override fun onPanelExpanded(view: View) {
toast("panel expand")
}
override fun onPanelAnchored(view: View) {
toast("panel anchored")
}
override fun onPanelHidden(view: View) {
toast("panel is Hidden")
}
}
}
In Java code, in onCreate method, I have:
slidingLayout.setPanelSlideListener(onSlideListener());
which doesn't seems to work in Kotlin, because the methods I have are Click, Drag, Hover, Key and Touch (listeners).
I guess other good approach could be to implement
SlidingPaneLayout.PanelSlideListener
on my class, but I still couldn't make it work.
Any solution to find up if the panel is displayed or hidden in Kotlin?
You need to load up the Slidinglayout.
private lateinit var slidingLayout: SlidingUpPanelLayout
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.activity_main, container, false).also {
slidingLayout = it.findViewById(R.id.sliding_Layout)
}
}
than you check for the PanelState
if (slidingLayout.panelState == SlidingUpPanelLayout.PanelState.HIDDEN)
You also have the states ANCHORED, EXPANDED, COLLAPSED, DRAGGING
If you want to set up the Listener in Kotlin I have done it like This.
slidingLayout.addPanelSlideListener(object : SlidingUpPanelLayout.PanelSlideListener {
override fun onPanelSlide(panel: View?, slideOffset: Float) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onPanelStateChanged(panel: View?, previousState: SlidingUpPanelLayout.PanelState?, newState: SlidingUpPanelLayout.PanelState?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
})

Android - programmatically change the state of a switch without triggering OnCheckChanged listener

I'm looking for a method of programmatically changing the state of an Android Switch widget using switch.setChecked(true); without triggering OnCheckedChangedlistener. My first thought was to swap it out for an OnClickListener but as this only registers clicks and you are able to not only click but also slide a Switch then it's not really fit for purpose as if the user was to slide the Switch from off to on then the Switch would actually do nothing as the user is not clicking...If anyone's got a solution or a smart work around for this, that would be awesome
Set the listener to null before calling setCheck() function, and enable it after that, such as the following:
switch.setOnCheckedChangeListener (null);
switch.setChecked(true);
switch.setOnCheckedChangeListener (this);
Reference: Change Checkbox value without triggering onCheckChanged
Every CompoundButton (two states button - on/off) has a pressed state which is true only when a user is pressing the view.
Just add a check in your listener before starting the actual logic:
if(compoundButton.isPressed()) {
// continue with your listener
}
That way, changing the checked value programmatically won't trigger the unwanted code.
From #krisDrOid answer.
Well, just before doing things in code with the switch you could just unregister the Listener, then do whatever you need to, and again register the listener.
I have one solution and its working fine at my end.
I have added setOnTouchListener and setOnCheckedChangeListener on my switch control, and added following code to solve my problem.
// set tag by default.
mMySwitch.setTag("TAG");
// Add OnCheckedChangeListener.
mMySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mMySwitch.getTag() != null) {
mMySwitch.setTag(null);
return;
}
// Do your stuff here.
}
});
// Add Touch listener.
mMySwitch.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mMySwitch.setTag(null);
return false;
}
});
In this way setOnCheckedChangeListener is getting called only when check changed happens by human intervention by drag, by click, by touch.
Also don't forgot to add your valid string tag ( not null ) when your trying to change check status of switch control.
like :
mMySwitch.setTag("TAG");
mMySwitch.setChecked(true);
Write a custom Switch or SwitchCompat and override the setOnCheckedListener.
public class SwitchCompat extends android.support.v7.widget.SwitchCompat {
private boolean mIgnoreCheckedChange = false;
public SwitchCompat(Context context) {
super(context);
}
public SwitchCompat(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwitchCompat(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setOnCheckedChangeListener(final OnCheckedChangeListener listener) {
super.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mIgnoreCheckedChange) {
return;
}
listener.onCheckedChanged(buttonView, isChecked);
}
});
}
public void setChecked(boolean checked, boolean notify) {
mIgnoreCheckedChange = !notify;
setChecked(checked);
mIgnoreCheckedChange = false;
}
}
the best solution I can find is;
const val SWITCH_COMPAT_IGNORE_TAG = "SWITCH_COMPAT_IGNORE_TAG"
fun SwitchCompat.isCheckedWithIgnoreTag(isChecked: Boolean) {
tag = SWITCH_COMPAT_IGNORE_TAG
this.isChecked = isChecked
tag = null
}
switchCompat.isCheckedWithIgnoreTag(true)
switchCompat.setOnCheckedChangeListener { buttonView, isChecked ->
if (buttonView.tag != SWITCH_COMPAT_IGNORE_TAG) {
//TODO
}
}
Based on the answers from #ronginat and #hyb1996 I made SensibleSwitch so that you can just drop it in your XML layouts, use the listener as you would expect to and not worry about it.
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.SwitchCompat
class SensibleSwitch : SwitchCompat {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun setOnCheckedChangeListener(listener: OnCheckedChangeListener?) {
super.setOnCheckedChangeListener { compoundButton, isChecked ->
if (isPressed) {
listener?.onCheckedChanged(compoundButton, isChecked)
}
}
}
}
switch.setOnCheckedChangeListener
{
compoundButton, check
if (switch.isPressed || switch.isSelected)
if (check) {
TODO("")
} else {
TODO("")
}
}
Elaborating on Mahmoud's answer
CompoundButton.OnCheckedChangeListener switchListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
switchListener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
//Implement on check change
}
};
switch.setOnCheckedChangeListener (switchListener);
//When you want to trigger the checked of switch do the following
switch.setOnCheckedChangeListener (null);
switch.setChecked(true);
switch.setOnCheckedChangeListener (switchListener);
}
`
use this
switch.setChecked(true); // first set value (from pref or server or anywhere) and than switch.setOnCheckedChangeListener (this); add listener.
If nothing worked here is a tricky solution.
Create a textview on top of the switch and add clickListener to textview.
<TextView
android:elevation="1dp"
android:id="#+id/switchLabel"
android:layout_width="0dp"
android:layout_height="0dp"
android:text=""
app:layout_constraintBottom_toBottomOf="#id/switch1"
app:layout_constraintStart_toStartOf="#+id/switch1"
app:layout_constraintTop_toTopOf="#id/switch1"
app:layout_constraintEnd_toEndOf="#id/switch1" />
Add elavation to textview.
For the default switch writed <Switch/> on xml,
do this in kotlin to set it programmatically :
mySwitch.isChecked = true
Then, if you want to do some action when user click on it:
mySwitch.setOnCheckedChangeListener { compoundButton, isChecked ->
when (isChecked) {
true -> { /* do something here*/ }
false -> { /* do something here*/ }
}
}

Blocking EditText contextMenu

I want to create an EditText with the following changes:
Clicking on it will not show the keyboard
After SINGLE, SHORT click it will get into selection mode (When I say selection mode I mean the mode where you can select a section of the text (with two pointers). You can get to this mode by long clicking on the text.)
After text is selected the copy/paste/cut toolbar will not be shown
For the first, I guess I can create an OnTouchListener and return true immediately, but then it will block me from doing the second thing (which I have no idea how to do).
I looked for a command that gets the EditText into selection mode, but all I could find was a way to get the selected text from it...
Thanks!
EDIT: I successfully made 1 and 2, but the toolbar still shows (tried unregisterForContextMenu)
you can use edittex.setCustomSelectionActionModeCallback
setCustomSelectionActionModeCallback(new Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
this will be block to open contextmenu for edittex

Categories

Resources