I have a table of FrameLayout where each frame contains either an ImageView or a TextView. Regardless of content in the frame I want the onClick event to be detected by the OnClickListener set on the frame.
How can I achieve this?
This is some of my layout, I got a total of 5 rows (Here's only shown 1).
As described above I have 5 FrameLayouts in each row, each containing a TextView. I am not able to put my OnClickListener on the TextView since this may be changed to an ImageView at runtime. Therefore i want the OnClickListener on the FrameLayout.
It seems that the content of the FrameLayout is preventing it from detecting the click event.
<TableLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/gateContainer"
android:stretchColumns="*">
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/door1"
android:clickable="true">
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="New Text"
android:id="#+id/textView"
android:layout_gravity="center" />
</FrameLayout>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/door2" >
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="New Text"
android:id="#+id/textView5"
android:layout_gravity="center" />
</FrameLayout>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/door3" >
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="New Text"
android:id="#+id/textView4"
android:layout_gravity="center"/>
</FrameLayout>
</TableLayout>
Here is an example of how i set the OnClickListeners:
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v){
// do something
}
};
TableLayout tableLayout = (TableLayout) findViewById(R.id.gateContainer);
// Go through all TableRows
for (int i = 0; i < tableLayout.getChildCount(); i++){
TableRow tableRow = (TableRow) tableLayout.getChildAt(i);
// Set listener for each FrameView
for (int j = 0; j < tableRow.getChildCount(); j++){
FrameLayout frame = (FrameLayout) tableRow.getChildAt(j);
frame.setOnClickListener(clickListener);
}
}
You could also set android:clickable="false" to the TextView/ImageView layouts and android:clickable="true" on the background, that way the background view always catches the clicks.
Additionally, the following answer might be helpful for people considering this issue:
SO: Android: How to propagate click event to LinearLayout childs and change their drawable
Just implement, OnTouchListener over ImageView and TextView components and duck them, in the sense pass them.
<your_view>.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return true;
}
});
this will make sure, your container handles that.
You can define the click event on your TextView or ImageView as below:
<yourView>.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// your logic here.
}
});
Related
I am adding pictures to a linearlayout programmatically. This linearlayout is surrounded by a horizontalscrollview and part of a item layout for a listview. When I have the pictures inline with the other view items, they are spaced next to eachother correctly:
However if I move the horizontalscrollview/linearlayout under the other view items, I get some weird spacing that android seems to do automatically:
So far I have tried relativelayouts, embedded linearlayouts, changing padding, changing margins, changing the width property of the linearlayout between match_parent, fill_parent, and wrap_content, but nothing changes this spacing. It is always the same.
Here is the relevant code:
LinearLayout tmpLL = (LinearLayout) convertView.findViewById(R.id.llUpgrades);
//remove previous list contents first
tmpLL.removeAllViews();
for(int i = 0; i<= tmpUpgradeList.size()-1; i++){
ImageView tmpIB = new ImageView(getContext());
Upgrade tmpUpgrade = tmpUpgradeList.get(i);
Upgrade.setUpgradePic(tmpIB, tmpUpgrade, tmpUpgrade.Title()==null);
tmpIB.setTag(position + ":" + i);
tmpIB.setPadding(5, 0, 0, 0);
tmpIB.setMaxWidth(50);
tmpLL.addView(tmpIB);
tmpIB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String[] split = ((String) v.getTag()).split(":");
runUpgradePopup(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
}
});
tmpIB.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
String[] split = ((String) v.getTag()).split(":");
clearUpgrade(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
return true;
}
});
}
Layout of the one causing the error. The other layout puts the cards next to each other correctly but all I have different is that it is a linear layout and removed the relevant relative placement calls:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<Button
android:layout_width="100dp"
android:layout_height="60dp"
android:id="#+id/btnFRemoveShip"
android:text="Remove"/>
<ImageView
android:id="#+id/ivFRowShipIcon"
android:layout_height="60dp"
android:layout_width="75dp"
android:src="#android:drawable/ic_delete"
android:layout_marginLeft="10dp"
android:layout_toRightOf="#+id/btnFRemoveShip"/>
<TextView
android:layout_height="wrap_content"
android:ems="10"
android:layout_width="wrap_content"
android:id="#+id/tvFRowShipTitle"
android:text="error"
android:textSize="20dp"
android:layout_marginLeft="10dp"
android:layout_toRightOf="#+id/ivFRowShipIcon"/>
<HorizontalScrollView
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="75dp"
android:layout_marginTop="5dp"
android:layout_below="#+id/btnFRemoveShip">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/llUpgrades">
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
Any help is greatly appreciated!
Took a couple days of rewording the question but finally found the answer.
Had to add this line before adding the image to the layout.
tmpIB.setAdjustViewBounds(true);
Thread is here: found answer
I am new to android and i am unable to solve my simple problem.I have a parent Tablelayout and inside it i have two tablelayouts with ids tbl1 and tbl2 respectively in my xml file.In tbl1 layout i have three textviews and three edittext controls similarly i have some views in tbl2 layout.Now i want that my tbl1 layout is visible when my activity starts but on click of my button2 which is in tbl1 layout my tablelayout tbl1 gets invisible and my tablelayout tbl2 becomes visible.Actually i know i can achieve this in asp.net with the help of panels but in android i am not able to achieve the same thing.Please help
You are going to want to look at the setVisibility() method. In the on click listeners for button 2, put the following;
Button.setVisibility(View.INVISIBLE)
TextView.setVisibility(View.INVISIBLE)
etc...
This will make the views invisible, but they will still take up space. If you don't want them to take up space you should use
setVisibility(Veiw.GONE);
Finally, to make you buttons and textview and edittexts in the second table, appear, you need to do the following;
setVisibility(View.VISIBLE);
Java Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.visibility_1);
// Find the view whose visibility will change
mVictim = findViewById(R.id.victim);
// Find our buttons
Button visibleButton = (Button) findViewById(R.id.vis);
Button invisibleButton = (Button) findViewById(R.id.invis);
Button goneButton = (Button) findViewById(R.id.gone);
// Wire each button to a click listener
visibleButton.setOnClickListener(mVisibleListener);
invisibleButton.setOnClickListener(mInvisibleListener);
goneButton.setOnClickListener(mGoneListener);
}
OnClickListener mVisibleListener = new OnClickListener() {
public void onClick(View v) {
mVictim.setVisibility(View.VISIBLE);
}
};
OnClickListener mInvisibleListener = new OnClickListener() {
public void onClick(View v) {
mVictim.setVisibility(View.INVISIBLE);
}
};
OnClickListener mGoneListener = new OnClickListener() {
public void onClick(View v) {
mVictim.setVisibility(View.GONE);
}
};
}
XML Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:background="#drawable/box"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:background="#drawable/red"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/visibility_1_view_1"/>
<TextView android:id="#+id/victim"
android:background="#drawable/green"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/visibility_1_view_2"/>
<TextView
android:background="#drawable/blue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/visibility_1_view_3"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button android:id="#+id/vis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/visibility_1_vis"/>
<Button android:id="#+id/invis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/visibility_1_invis"/>
<Button android:id="#+id/gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/visibility_1_gone"/>
</LinearLayout>
</LinearLayout>
This is my xml file and as you can see it is nested many times by Linear layout.
What i want to acheive is when I click on the area of llOptionA(First
Linear Layout) i will get notified by a toast.
I have also put a toast on llOptionA.setonclickListener()
But when i click on the text it does nothing.
then I also set onclicklisteners on each of them giving me different toasts -> svTest ,layout_inner ,tvOptionA. and also i clicked everywhere to see which part is showing which toast.
<LinearLayout
android:id="#+id/llOptionA"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ff00ff"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:paddingTop="5dp" >
<HorizontalScrollView
android:id="#+id/svTest"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/layout_inner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/tvOptionA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="A - Option A "
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#ffffff"
android:textStyle="bold" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
First a LinearLayout does not listen for click events by default even when you set an OnClickListener. You also need to add this attribute to your LinearLayout llOptionA:
android:clickable="true"
Second a click starts at the highest level, TextView tvOptionA, and works it's way down until a View consumes this event. So before it reaches llOptionA your HorizontalScrollView intercepts the click in it's default OnTouchListener and doesn't pass it down to your llOptionA... You can listener for a click event with an OnTouchListener in your HorizontalScrollView to call the appropriate method.
Third perhaps this is a simplified layout, but the LinearLayout layout_inner only has one child and therefor is not necessary, you can simply use this:
<LinearLayout ...>
<HorizontalScrollView ...>
<TextView .../>
</HorizontalScrollView>
</LinearLayout>
Of course llOptionA only has one child so you could simplify it more:
<HorizontalScrollView ...>
<TextView .../>
</HorizontalScrollView>
Addition from comments
Here is how to put it all together:
public class Example extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.llOptionA);
linearLayout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
toast();
}
});
HorizontalScrollView hsv = (HorizontalScrollView) findViewById(R.id.svTest);
hsv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP)
toast();
return false;
}
});
}
public void toast() {
Toast.makeText(this, "Click", Toast.LENGTH_SHORT).show();
}
}
I Have activity that get some data from the internet, and shows it to the screen.
I'm using scroll view cause it's long text, I also want different text style for a different data,so I use few textViews with a different style and to show it on the Activity screen,
my problem is that scroll view can handle only one view, so how can I use scrolling to show different style of Text view, I tried to add LinearLayout to the scrollView and add all the textViews dynamically in code to this LinearLayout ,but I'm getting exception - scroll view can host only one direct child.
The code below:
/** this is the function, which called from the onClick method.
wanted data object contains 2 strings title message and the message itself.
When debug the code i can see that there's two String values in each loop.
but i cant add the linearLayout to my scrollView - exception ScrollView can host only one direct child */
private void showResult(ArrayList<WantedData> result) {
// TODO Auto-generated method stub
TextView title;
TextView data;
scrollLayout = (LinearLayout) findViewById(R.id.LlScrollView);
for (WantedData curr : result) {
if (curr.getTitle() == null) {
break;
}
title = new TextView(this);
title.setText(curr.getTitle());
scrollLayout.addView(title, LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
data = new TextView(this);
data.setText(curr.getData());
scrollLayout.addView(data, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
}
scroll.addView(scrollLayout, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
//at the onCreate method - scroll = (ScrollView) findViewById(R.id.SvShowTextFromServer);
}
the xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<include
android:id="#+id/layout_reffernce"
layout="#layout/explore" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Enter City" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/EtCity"
android:layout_width="210dp"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:orientation="vertical" >
<requestFocus />
</EditText>
<Button
android:id="#+id/bSearchCity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Enter State" />
<EditText
android:id="#+id/EtState"
android:layout_width="253dp"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
<ScrollView
android:id="#+id/SvShowTextFromServer"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/LlScrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/backround"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
</LinearLayout>
The problem is double creating of container in ScrollView. You should not create it in activity, but take already defined from xml:
LinearLayout scrollContainer = (LinearLayout)findViewById(R.id.LlScrollView);
for (...) {
//create here some text
scrollLayout.addView(text);
}
If you have defined a LinearLayout in XML you don't have to create a new LinearLayout in your code but you have to retrieve the existing one in this way
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.LlScrollView);
Otherwise you have to remove the LinearLayout in your XML and add all by code.
I have an tableview which i want to scroll, because the data is not shown complete.
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="0,1,2,3,4"
android:id="#+id/maintable" >
</TableLayout>
this is my tablelayout, and if i wrap it in an <ScrollView> </Scrollview> the Application crashs if i open the activity. How to do that?
You should really put the code you tried that crashed your application and the reason for your crash. There's no valuable information in your original post.
Ehhh... did you try something as simple as this? Example .xml that I use a few places:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout android:id="#+id/score_table"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableRow android:id="#+id/header"/>
</TableLayout>
</ScrollView>
Works absolutely fine for me. You don't have to include the TableRow if you have no use for it, obviously.
Create your rows dynamically
Here I am putting a small example,
main.xml
<Button android:id="#+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add row"></Button>
<ScrollView android:id="#+id/ScrollView01" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TableLayout android:id="#+id/TableLayout01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0">
<TableRow android:id="#+id/TableRow01" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:id="#+id/TextView01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="textfield 1-1"></TextView>
<CheckBox android:id="#+id/CheckBox01" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox>
</TableRow>
</TableLayout>
</ScrollView>
Activity is
public class tablelayout extends Activity implements OnClickListener {
/** Called when the activity is first created. */
//initialize a button and a counter
Button btn;
int counter = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setup the layout
setContentView(R.layout.main);
// add a click-listener on the button
btn = (Button) findViewById(R.id.Button01);
btn.setOnClickListener(this);
}
// run when the button is clicked
public void onClick(View view) {
// get a reference for the TableLayout
TableLayout table = (TableLayout) findViewById(R.id.TableLayout01);
// create a new TableRow
TableRow row = new TableRow(this);
// count the counter up by one
counter++;
// create a new TextView
TextView t = new TextView(this);
// set the text to "text xx"
t.setText("text " + counter);
// create a CheckBox
CheckBox c = new CheckBox(this);
// add the TextView and the CheckBox to the new TableRow
row.addView(t);
row.addView(c);
// add the TableRow to the TableLayout
table.addView(row,new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
}
You can create your table row, when in your code require. I assumed it is on button click.
Hope this will help.
And here one more example.