How to make EditText's parent clickable? - android

Suppose I have this pink box:
It consists of LinearLayout with its children: TextView as field name and an EditText. EditText is intentionally disabled. What I want is that, user can click wherever user wants on that pink box. By the way, please just ignore any UI/UX things that you found weird.
I've tried, but user can't tap the area that EditText occupies. User have to tap in TextView or blank area on pink box so that the apps got the 'click'. But if user taps on EditText's area, nothing will happen.
I've tried playing with some things in xml's properties, such as set LinearLayout's clickable to true, and all children or just EditText's properties of clickable, focusable, and focusableInTouchMode to false, all to no avail. EditText area still cannot be clicked.
Any idea? Can't it be reached just through xml? Should it be done programmatically just to turn bypass EditText's click?

You can simply add onTouch Listener instead of click Listener.

You need to request the parent layout (LinearLayout, whatever) and loop through the views if you dont want to bind them all. If you use databinding its easier. Anyway, here is a solution (a small piece of code is required!).
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="out of focus"/>
<LinearLayout
android:id="#+id/linearTest"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test for clicking"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="another clicking test"
/>
<EditText
android:id="#+id/editTest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="focus edittext when clicking linearlayout or other elements inside"
/>
</LinearLayout>
</LinearLayout>
Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.linear_focus_test);
final EditText editText = (EditText) findViewById(R.id.editTest);
LinearLayout linearTest = (LinearLayout) findViewById(R.id.linearTest);
for (int i = 0; i < linearTest.getChildCount(); i++)
View v = linearTest.getChildAt(i);
v.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
editText.requestFocus();
}
});
}
}
If you dont like boilerplate you may also use lambda (use 1.8 features)
for (int i = 0; i < linearTest.getChildCount(); i++)
linearTest.getChildAt(i).setOnClickListener(v1 -> editText.requestFocus());
If you use at least API 24 you can even make it shorter:
IntStream.range(0, linearTest.getChildCount()).forEach(i -> linearTest.getChildAt(i).setOnClickListener(v1 -> editText.requestFocus()));

Related

How do I add android views in run time with dynamic ID's

I am making an app where at a certain fragment, I need a variable number of EditTexts in the fragment. I have an add button below the layout which when pressed should add the required Edit Text with ID's so that I can collect data from it.
For eg, if the layout starts out with
When I press the + button, it should add like
So as I keep pressing the + button, I should automatically get one more layout with all the edit texts.
And I need a way to keep track of the ids of all the edit texts so that I can get all the data later.
How do I go about doing this???
Design your layout of EditText's in xml as a my_item.xml file :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="#+id/et1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="#+id/et2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="#+id/et3"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
In your fragment add a LinearLayout to add dynamic items in it and a Button like this:
<LinearLayout
android:id="#+id/ll_dynamicItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"></LinearLayout>
<Button
android:id="#+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+" />
Now in java code we inflate the my_item layout and add it to ll_dynamicItems. We also need a List of LinearLayout's to store inflated layout's in it:
List<LinearLayout> myLayouts = new ArrayList<>();
btn_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LinearLayout ll = (LinearLayout) getLayoutInflater().from(getApplicationContext()).inflate(R.layout.my_item, ll_dynamicItems, false);
myLayouts.add(ll);
ll_dynamicItems.addView(ll);
}
});
Now for get a first layout first EditText value, you can do like this:
((EditText) myLayouts.get(0).findViewById(R.id.et1)).getText()
For get a second layout third EditText:
((EditText) myLayouts.get(1).findViewById(R.id.et3)).getText()
For reading all EditText's value you can track the list with a for ;)
Actually you can take linearlayout vertical orientation and add edittexts whenever user presses plus button,programatically you can add to layout.
you maintain some random numbers you add it
EditText ed = new EditText(this);
ed.setId(1);
ed.setText("" + i);
ed.setInputType(2);
ed.setLayoutParams(lparams);
textFieldsLayout.addView(ed)

TabLayout : Set custom color for each tab

I saw a lot of questions that say how to set the color differently for selected(active) and unselected(inactive) tabs. I also know that google provides void setTabTextColors (int normalColor, int selectedColor) to achieve this.
My requirement is a little different, I am working on a quiz app with a TabLayout and CardView. TabLayout allows the user to navigate between questions and CardView is used to display the questions.
I need to set the color of the tabs for which the user has already selected an answer differently than that for which the user has not answered yet. By default the TextColor is black but if the user selects an answer then the tabcolor should change to blue (just for eg.) and it should remain that way till the user exits. I have a int array called Select that will hold the value of the option that the user has selected (The values range between 1 - 4). While allocating the Select array I also initialize it with -1. I thought of setting up a loop and then if the array is -1 leave the tab as it is or set the tabcolor to blue.
How can I achieve this functionality?
You can work with TabLayout internals by querying for this children and changing TextViews manually. This can break your code when you upgrade to another support library version, but as long as you keep track and test when updating, it should work:
private void updateTabTextColors() {
LinearLayout tabsContainer = (LinearLayout) mTabLayout.getChildAt(0);
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
LinearLayout item = (LinearLayout) tabsContainer.getChildAt(i);
TextView tv = (TextView) item.getChildAt(1);
tv.setTextColor(Select[i] == -1 ? Color.BLACK : Color.BLUE);
}
}
Just enhancing Marcelo Liberato's answer to support custom background for each tab item.
LinearLayout tabsContainer = (LinearLayout) mTabLayout.getChildAt(0);
LinearLayout childLayout1 = (LinearLayout)tabsContainer.getChildAt(2);
LinearLayout childLayout2 = (LinearLayout)tabsContainer.getChildAt(3);
LinearLayout tabView = (LinearLayout) childLayout1.getChildAt(0).getParent();
tabView.setBackgroundResource(R.drawable.ic_blue_selector);
tabView = (LinearLayout) childLayout2.getChildAt(0).getParent();
tabView.setBackgroundResource(R.drawable.ic_red_selector);
Custom xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/ll_tab_holder"
android:orientation="vertical">
<LinearLayout
android:id="#+id/ll_tab_icon_title_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/tab_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:scaleType="fitCenter" />
<TextView
android:id="#+id/tab_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textAppearance="#style/lasuCustomTabText" />
</LinearLayout>
<TextView
android:id="#+id/tab_only_title"
android:layout_width="match_parent"
android:layout_height="56dp"
android:textAllCaps="true"
android:textSize="12sp"
android:layout_gravity="center"
android:gravity="center"
android:textColor="#drawable/ic_tab_text_color_selector" />
</LinearLayout>
Output:
If you are interested in using a library for this functionality, this library works well.
https://github.com/astuetz/PagerSlidingTabStrip
As in the doc getTabTextColors() -> Gets the text colors for the different states (normal, selected) used for the tabs. the tabs can only have 2 states. The only way to achieve what you want if to inherit Tab class and add a new state, something like: tabAlreadyVisited. Then #Override the draw method to change background color based on the tabAlreadyVisited attribute value. Or change the text color with setTabTextColors
It's possible to set custom view for your tab
TabLayout.Tab yourTab = tabLayout.newTab();
yourTab.setCustomView(R.layout.red_text_view);
And red_text_view.xml is
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:textColor="#f44336"/>
If you use the #android:id/text1 default Tab's settext should work. You could do whatever you want with your custom view.

Android - propagating click from parent to child

I have a LinearLayout with a couple of TextViews stacked vertically. I want to attach a click listener to the parent and make the click event propagate to one of the TextViews (child views of the containing LinearLayout).
I understand that I can attach click listener's to the individual TextViews and achieve the same result but I'd like to do otherwise.
I came across the
android:duplicateParentState="true"
attribute, but this doesn't seem to solve the issue either. What should I be doing to get the child views to consume the containing parent's click event. Also each text view should perform a different action.
Here is the layout:
<?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:id="#+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text_1"
android:duplicateParentState="true"
android:layout_marginBottom="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:text="Text_2" />
</LinearLayout>
And here is the Activity:
public class MainActivity extends AppCompatActivity {
LinearLayout mLinearLayout;
TextView mTextView1;
TextView mTextView2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLinearLayout = (LinearLayout) findViewById(R.id.linear_layout);
mLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.v("view",view.toString());
}
});
}
}
The log always prints the parent view:
V/view: android.widget.LinearLayout{3ea32ab0 V.E...C. ...PH... 0,0-1080,1533 #7f0c0050 app:id/linear_layout}
V/view: android.widget.LinearLayout{3ea32ab0 V.E...C. ...PH... 0,0-1080,1533 #7f0c0050 app:id/linear_layout}
I am obviously missing something here and hopefully the solution doesn't involve navigating down the view stack. What am I doing wrong, any help would be most appreciated.
You may use setOnTouchListener for your LinearLayout. Inside this OnTouchListener you need to detect a click (GestureDetector can help) in this point you will have MotionEvent, you can get x,y coordinates from this event and compare them with your TextViews coordinates. So you can detect which TextView was clicked. In such a way you can do what you want, but it is complicated, and I believe you can avoid it.

LinearLayout's click listener is never called

Trying to get an onclick listener working on a linearlayout but its never called :(. Have enabled clickable and focsuable (both modes) and still cant get the click listener to respond. Platform details: Android 3.0.. Any help?? Code below
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/menu_items_button"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingTop="#dimen/gen_margin_xsmall"
android:paddingBottom="#dimen/gen_margin_xsmall"
android:background="#drawable/rule_bg_menu_button"
android:clickable="true"
android:focusableInTouchMode="true"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/menu_items"
android:tag="image"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="text"
android:text="#string/menu_items_icon_txt"
style="#style/textDisplay.mediumLarge"
/>
</LinearLayout>
and in the code to add the event listener
_itemsButton = (LinearLayout) menu.findViewById(R.id.menu_items_button);
final Intent itemsIntent = new Intent(this, ItemsActivity.class);
_itemsButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(itemsIntent); //Never called!
}
}
);
The reason I'm doing this and not using an Image button instead is because the background of the "button" is state based (gradient changes) but also the image and in order to combine to the two on click / on focus, I used a linearlayout which has an ImageView in itself.. any suggestions on why the clickListener is not working on the linearLayout?
thx
Did the click go to the ImageView instead of the LinearLayout? Try clicking in the pad area (if any) or try putting the click listenner on the ImageView1.
(adding my response as a new answer so that I can use the PRE tag.)
The easy way is to set the same click listener on the image view and the text view.
View.OnClickListener activityLauncher = new View.OnClickListener() {... }
layout.setOnClickListener(activityLauncher);
imageView.setOnClickListener(activityLauncher);
textView.imageView.setOnClickListener(activityLauncher);
The width of your LinearLayout is set to "0dip", you should see nothing on the screen.
If the width is changed to "FULL_PARENT", that works. Please check your code carefully again.

EditText with cross(x) button at end of it

Is there any way to add the x-graphics in the android Editbox like the of iPhone
So that by clicking on that x graphic it can clear all the values in the Editbox
Is there any way to listen weather i touch a specific part of an edit text
Thank you
Yes there is a way to achieve this.
Define a RelativeLayout like this one.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText android:id="#+id/edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"/>
<ImageButton android:id="#+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon"
android:layout_alignRight="#id/edittext"/>
</RelativeLayout>
Now what happens. The ImageButton gets drawn on top of the EditText. We set its right edge to be equal to the right edge of the EditTexts in order to get it appear on the right side.
Now you have to assign your ImageButton an OnCLickListener with if overridden method to just set the EditTexts text to a empty string like that.
EditText editText = null;
ImageButton clear = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.clear);
editText = (EditText) findViewById(R.id.edittext);
clear = (ImageButton) findViewById(R.id.clear);
clear.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
editText.setText("");
}
});
}
Now here we simply tell our ImageViews OnClickListener to reset our EditTexts text upon a click. Simple as that. ;)
Of course my example uses not very aesthetic images but you can fine tune the images yourself. The principle works.
You can download it, it works like iPhone
https://github.com/GhOsTTT/editTextXbutton

Categories

Resources