I want to toggle textView on click.
val targetView = findViewById<TextView>(R.id.targetText)
targetView.text = 'example'
targetView.setOnClickListener {
if (it.visibility == View.VISIBLE) {
it.visibility = View.INVISIBLE
} else {
it.visibility = View.VISIBLE
}
}
But once I clicked and visibility of text was changed to invisible, then I can not click this again.
Suggestion: How about creating a view behind the text and make use of the view for toggle triggering instead of text.
i.e. onViewClicked { toggleTextVisibility() }
Store the text of the textview in a temporary string. Instead of toggling the visibility, set the text to null and then back to what it was using the temp variable.
String final tempText = "your text"
then
targetView.setOnClickListener(new View.OnClickListener) {
#Override
public void onClick(View view){
if (view.getText() == null) {
view.setText(tempText);
} else {
view.setText(" ");
}
});
}
just make sure your textview on the layout properties has a set minWidth and not wrap_content as it will disappear when you set the text to null
Related
I want 3 things to change when i click on my imagbutton if boolean is true:
backgroundcolor
set edittext: focusable, clickable
backgroundresource
But only the backgroundcolor is working. The resource doesnt change and the focusable and clickable of the edittext is always false
editfirst.setOnClickListener(new View.OnClickListener() {
boolean check;
#Override
public void onClick(View v) {
if (check == true){
editfirst.setBackgroundResource(R.drawable.edit36px);
editfirst.setBackgroundColor(0xFF99b6b3);
editTextfirst.setFocusable(false);
editTextfirst.setClickable(false);
check = false;
}
else if (check == false){
editfirst.setBackgroundResource(R.drawable.done36px);
editfirst.setBackgroundColor(0xFFb2b2b2);
editTextfirst.setFocusable(true);
editTextfirst.setClickable(true);
check = true;
}
}
});
editfirst.setBackgroundResource(R.drawable.edit36px);
editfirst.setBackgroundColor(0xFF99b6b3);
This will first set the background to edith36px and then replace it again with the color 0xFF99b6b3.
If you want to change the image on the image button you have to use setImageResource(int id).
If you want to disable a view you should use setEnabled(false). I don't think setting clickable to false is working if you have a click listener attached.
I know that setting android:textIsSelectable="true" in xml for the TextView will show the native text selection popup and I've been using that in my application. But what I found that it is not working any more when I try to set the same attribute in a view attached to the RecyclerView.
Whenever I try to select the text the following log appears -
TextView: TextView does not support text selection. Action mode cancelled.
And I don't know why? Why it works on other screens and not with the RecyclerView. I read multiple posts -
TextView with android:textIsSelectable="true" not working in listview
textview textIsSelectable="true" not working in Listview
android:textIsSelectable="true" for TextView inside Listview does not work
But then I encountered this post -
Android: "TextView does not support text selection. Action mode cancelled"
And the reply by #hungkk worked for me. His solution suggested the TextView width to change to wrap_content from match_parent.
I know I can do this but my question is how this fixed the issue because it looks weird to me. And also, what is the solution if I want to keep the width to match_parent.
Any inputs are welcome.
In the main-parent layout of recyclerview add attribute
android:descendantFocusability="beforeDescendants"
and then in TextView of rowitem layout add
android:textIsSelectable="true"
I found TextView in RecyclerView can select first time ,but when ViewHolder was recycled or adapter notifyDataSetChanged,all text view will can't be selected.
And I found this solution was working for me.
yourTextView.setText("your text");
yourTextView.setTextIsSelectable(false);
yourTextView.measure(-1, -1);//you can specific other values.
yourTextView.setTextIsSelectable(true);
Why do this? because I have debugged and found some logic in android source code:
TextView.java:
public void setTextIsSelectable(boolean selectable) {
if (!selectable && mEditor == null) return; // false is default value with no edit data
createEditorIfNeeded();
if (mEditor.mTextIsSelectable == selectable) return;
mEditor.mTextIsSelectable = selectable;
setFocusableInTouchMode(selectable);
setFocusable(FOCUSABLE_AUTO);
setClickable(selectable);
setLongClickable(selectable);
// mInputType should already be EditorInfo.TYPE_NULL and mInput should be null
setMovementMethod(selectable ? ArrowKeyMovementMethod.getInstance() : null);
setText(mText, selectable ? BufferType.SPANNABLE : BufferType.NORMAL);
// Called by setText above, but safer in case of future code changes
mEditor.prepareCursorControllers();
}
Editor.java
void prepareCursorControllers() {
boolean windowSupportsHandles = false;
ViewGroup.LayoutParams params = mTextView.getRootView().getLayoutParams();
if (params instanceof WindowManager.LayoutParams) {
WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
windowSupportsHandles = windowParams.type < WindowManager.LayoutParams.FIRST_SUB_WINDOW
|| windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
}
boolean enabled = windowSupportsHandles && mTextView.getLayout() != null;
mInsertionControllerEnabled = enabled && isCursorVisible();
**mSelectionControllerEnabled = enabled && mTextView.textCanBeSelected();**
if (!mInsertionControllerEnabled) {
hideInsertionPointCursorController();
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.onDetached();
mInsertionPointCursorController = null;
}
}
if (!mSelectionControllerEnabled) {
stopTextActionMode();
if (mSelectionModifierCursorController != null) {
mSelectionModifierCursorController.onDetached();
mSelectionModifierCursorController = null;
}
}
}
---> TextView.java
/**
* Test based on the <i>intrinsic</i> charateristics of the TextView.
* The text must be spannable and the movement method must allow for arbitary selection.
*
* See also {#link #canSelectText()}.
*/
boolean textCanBeSelected() {
// prepareCursorController() relies on this method.
// If you change this condition, make sure prepareCursorController is called anywhere
// the value of this condition might be changed.
if (mMovement == null || !mMovement.canSelectArbitrarily()) return false;
return isTextEditable()
|| (isTextSelectable() && mText instanceof Spannable && isEnabled());
}
you can debug in Emulator and trace this code.
If you add android:descendantFocusability="blocksDescendants" in the recyclerview or listview, then remove it.
And after check this
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
yourTextView.fixTextSelection()
}
fun TextView.fixTextSelection() {
setTextIsSelectable(false)
post { setTextIsSelectable(true) }
}
Add In Your RecyclerView Adapter:
public ViewHolder(View itemView) {
super(itemView);
txtDate = (TextView) itemView.findViewById(R.id.txtDate);
txtDate.setTextIsSelectable(true);
}
its worked for me..
There seems to be many that have problems with this and indications that it may be a bug in the Android code but I don't have a problem. This is what works for me both for an OnClickListener() and the native selection popup. (Tested on KitKat 4.4, Lollipop 5.1 and Nougat 7.1)
In the adapter
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView textView;
ImageView imageView;
MyViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.my_text_view);
imageView = (ImageView) itemView.findViewById(R.id.my_image_view);
itemView.setOnClickListener(this);
textView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
// this shows 'my_text_view' when the text is clicked or
// 'my_item' if elsewhere is clicked
Log.d(TAG, "view = " + view.toString());
switch (view.getId()) {
case R.id.my_item:
break;
case R.id.my_text_view:
break;
}
}
}
And my item layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/my_item"
>
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#color/colorPrimary"
android:id="#+id/my_image_view"
/>
<!-- this works for me with either "match_parent" or "wrap_content" for width -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="My text view"
android:textIsSelectable="true"
android:id="#+id/my_text_view"
/>
</LinearLayout>
If your TextView is inside ConstraintLayout, make sure the width is not wrap_content. With TextView width 0dp or match_parent this works fine.
I found I have to set the TextView text and its width after a while. So I put this attribute (android:textIsSelectable="true") in xml layout of TextView and post{} the width and the text in onBindViewHolder method of the recyclerView adapter like this:
class ContentAdapter(): ListAdapter<Verse, ContentAdapter.ViewHolder>(DiffCallback()) {
.
.
.
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getItem(position)
holder.bind(item)
}
class ViewHolder(val binding: ItemBinding): RecyclerView.ViewHolder(binding.root) {
fun bind(item: Verse){
binding.myTextView.apply{
val params = layoutParams as ConstraintLayout.LayoutParams
params.width = 100 /*any value you want for the width of your TextView*/
post{
layoutParams = params
text = item.text
}
}
}
companion object {
fun from(parent: ViewGroup): ViewHolder{
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ItemBinding.inflate(layoutInflater, parent, false)
return ViewHolder(binding)
}
}
}
}
Final And Working Solution
In Your onBindView write your code like this!
textView.text = "the content"
textView.setTextIsSelectable(false)
textView.post { txtContent.setTextIsSelectable(true) }
or advanced version could be writing an extension function on TextView
fun TextView.fixTextSelection(){
setTextIsSelectable(false)
post { setTextIsSelectable(true) }
}
and use it like this
textView.text = "the content"
textView.fixTextSelection()
I needed TextView which would flash on text change - so I made CustomTextView like described in here. It works great but I have problem when I set that CustomTextView in list item. Because of ListView items are being reused my CustomTextView keeps flashing when scrolling up/down because it's context changes and now it 'points' to another list item.
Problem is I don't know how to determine when context of the item is changed, so I cannot put noFlash flag (Text property of the CustomTextView is not set to null, so I cannot use that either)
On the end I had to make custom adapter with some code in BindBindbleCode
protected override void BindBindableView(object source, IMvxListItemView viewToUse)
{
var newValue = source as ListItemVM;
var oldValue = viewToUse.DataContext as ListItemVM;
if (newValue.ItemID != oldValue.ItemID)
newValue.Rebinded = true;
base.BindBindableView(source, viewToUse);
}
then I added NotLoaded property on CustomTextView and binded those two together. So when Rebinded is true it sets NotLoaded to true signalizing that data in that TextView is not loaded. If data is not loaded there's no need to flash background of CustomTextView.
public string AnimatingText
{
get { return Text; }
set
{
if (Text == value)
return;
if (NotLoaded)
{
Text = value;
NotLoaded = false;
return;
}
Text = value;
// Do your animation here
}
}
i am trying to expand textview in android, i have textview with some bulk content, my requirement is to display only two lines from bulk content with finishing (...). if i click it, my full content will has to display. how to
achieve this. could you please help me?
public class MainActivity extends ActionBarActivity {
TextView t1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t1 = (TextView) findViewById(R.id.text);
String str = "If your view subclass is displaying its own Drawable objects, it should override this function and return true for any Drawable it is displaying. This allows animations for those drawables to be scheduled." +
"I made the expandable list view acc to your tutorial but what i have to do if I want to populate Expandable List View with values from database?Means what changes I have to do in ";
t1.setText(str);
t1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
t1.setMaxLines(Integer.MAX_VALUE);
}
});
}
}
You can set android:maxLines property of textview to 2 by default in your layout xml..
In your onCreate() function after setting the text to your textview (t1).
Add following
boolean isTextViewClicked = false;
t1.setOnClickListener(new OnClickListener() {
if(isTextViewClicked){
//This will shrink textview to 2 lines if it is expanded.
t1.setmaxLines(2);
isTextViewClicked = false;
} else {
//This will expand the textview if it is of 2 lines
t1.setMaxLines(Integer.MAX_VALUE);
isTextViewClicked = true;
}
});
This will expand the textview as per the content
I describe the best and optimize approach in a medium article.
What you need to do is running the following function in a TextView.post{} function:
private fun TextView.setCaption(senderName: String, caption: String) {
text = getFullCaption(senderName, caption)
if (lineCount > DEFAULT_LINES) {
val lastCharShown = layout.getLineVisibleEnd(DEFAULT_LINES - 1)
maxLines = DEFAULT_LINES
val moreString = context.getString(R.string.read_more)
val suffix = " $moreString"
// 3 is a "magic number" but it's just basically the length of the ellipsis we're going to insert
val actionDisplayText = context.getString(R.string.more_dots) + suffix
text = SpannableStringBuilder()
.bold { append(senderName) }
.append(" ")
.append(
caption.substring(
0,
lastCharShown - suffix.length - 3 - moreString.length - senderName.length
)
)
.color(Color.GRAY) { append(actionDisplayText) }
}
}
Calling setCapton function in an extensive function of TextView and set click listener for it to expand, is your final step to have an expandable TextView:
private fun TextView.setExpandableText(senderName: String, caption: String) {
post {
setCaption(senderName, caption)
setOnClickListener {
let {
it.maxLines = MAX_LINES
it.text = getFullCaption(senderName, caption)
}
}
}
}
I want to set the background color of clicked TextView included in LinearLayout. But I am unable to set the respective background. I faced not
clear previous clicked background . if I clicked all then set all background color.
Would you suggest me ,
how to set clickable TextView included in LinearLayout background.
Here is my sample code:
holder.txtName = (TextView) convertView.findViewById(R.id.row_cell_text_dummy_multilevel);
holder.l_select = (LinearLayout) convertView.findViewById(R.id.linear_select);
holder.txtName.setTag(position);
holder.txtName.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
select_pos=(Integer) holder.txtName.getTag();
if (position==select_pos) {
holder.l_select.setTextColor(Color.RED);
}else {
holder.l_select.setTextColor(Color.WHITE);
}
}
});
I managed to get this much done, though you will have to do some homework and find out how to reflect the changes yourself. At the moment, the change gets reflected only when the view is scrolled.
But i hope it helps you.
1.declare a static variable that sets the position clicked on
private static int selectedPostion;
2.set the selectedPosition's value to -1 in the constructor
3.in the getView method in the onclickListener do this:
int value = (Integer)((TextView)v).getTag();
Log.e("tag","(TextView)v).getTag() : " + value);
Log.e("tag", "position : " + position);
if(value == position) {
selectedPostion = position;
}else {
selectedPostion = -1;
}
4.Under the onClick code entirely before return view write this:
if(selectedPostion == position) {
view.setBackgroundColor(mContext.getResources().getColor(R.color.even_color));
// or holder.l_select.setTextColor(Color.RED);
}else {
view.setBackgroundColor(mContext.getResources().getColor(android.R.color.white));
// or holder.l_select.setTextColor(Color.WHITE);
}
Hope it helps!