I have a simple Activity with its main.xml attached. main.xml has a custom layout (customLinearLayout) and a simple TextView. The custom layout also have its own layout-file (linearlayout.xml) with a simple Button. The layout is inflated by the class properly.
The Button in linearlayout.xml shall change the text of the textView lying in main.xml, but I can't get access to that textView. What am I doing wrong? I can't inflate the main.xml either.
Here's the customLinearLayout:
public class CustomLinearLayout extends LinearLayout {
LayoutInflater mInflater;
View ContainerView;
Button button1;
TextView tv;
public CustomLinearLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
private void init() {
mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ContainerView = mInflater.inflate(R.layout.linearlayout, this, true);
button1 = (Button) ContainerView.findViewById(R.id.button1);
// trying to get the TextView from main.xml
tv = (TextView) ContainerView.findViewById(R.id.textview1); // doesn't work
// these tries doesn't work either
//tv = (TextView) ContainerView.getRootView().findViewById(R.id.textview);
//tv = (TextView) this.getRootView().findViewById(R.id.textview);
//tv = (TextView) this.findViewById(R.id.textview);
button1.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if(tv != null)
tv.setText("works");
else
Log.d("CustomLinearLayout", "TextView not found");
}
});
}
}
the layout-file (linearlayout.xml):
<?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" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="press" />
</LinearLayout>
The Activity:
public class TestLayoutViewsv2Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
The Activity's main.xml:
<?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" >
<test.layoutviewsv2.CustomLinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
The method findViewById is scoped - your custom view is looking inside itself for a text field that doesn't exist. But that's ok! your views should be their own little world - They shouldn't need to know anything about the world outside itself. Sadly you'll have to change your design to accomodate this (like with a callback to the activity, perhaps) to make this do what you want to.
You are using the inflate method in a wrong way..there is no point of inflating a layout if you are extending a view. The inflate method is used to init a new view without the need to create a new instance yourself. I am not getting what your are trying to do but you could use the include to reuse some of your layouts. Check this for more info http://developer.android.com/resources/articles/layout-tricks-merge.html
Related
What I'm trying to do is to have a listview item with a button in each list viewitem.
When the Buttton is being pressed I want a layout that is at gone state will be visible and expand with animation down, and if the layout is shown than when the same button is being preesed than the layout will slide up and be gone again.
In order to do so I've created the next layout for the listview item -
<?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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tilte_info">
<TextView
android:id="#+id/textView_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:text="TextView"
android:textSize="20sp" />
<Button
android:id="#+id/button_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="25dp"
android:text="Open" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#5C83AF"
android:visibility="gone"
android:id="#+id/extend_info">
<TextView
android:id="#+id/textView_more_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:text="TextView"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
As you can see there are two layouts - one is tilte_info which is always shown and have the button in it, and the other one is extend_info which will be shown or hide by the button click.
Now I've used the next code in order to try and make it work -
public class MainActivity extends Activity {
ArrayList<Place> placesList = new ArrayList<Place>();
placeAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Place place1 = new Place("Place num 1", "some info on place 1");
Place place2 = new Place("Place num 2", "some info on place 2");
Place place3 = new Place("Place num 3", "some info on place 3");
placesList.add(place1);
placesList.add(place2);
placesList.add(place3);
ListView lv = (ListView) findViewById(R.id.listview_1);
adapter = new placeAdapter(this);
lv.setAdapter(adapter);
}
class placeAdapter extends ArrayAdapter<Place> implements OnClickListener{
public placeAdapter(Context context) {
super(context, -1, placesList);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView==null){
// use the LayoutInflater to inflate an XML layout file:
convertView=getLayoutInflater().inflate(R.layout.list_item, parent,false);
}
TextView textTitle = (TextView) convertView.findViewById(R.id.textView_title);
TextView textInfo = (TextView) convertView.findViewById(R.id.textView_more_info);
Button open = (Button) convertView.findViewById(R.id.button_open);
infoLayout = (View) convertView.findViewById(R.id.extend_info);
infoLayout.setVisibility(View.GONE);
open.setOnClickListener(this);
Place place = placesList.get(position);
textTitle.setText(place.getTitle());
textInfo.setText(place.getInfo());
return convertView;
}
#Override
public void onClick(View v) {
if(infoLayout.isShown()){
slide_up(MainActivity.this, infoLayout);
infoLayout.setVisibility(View.GONE);
}else{
infoLayout.setVisibility(View.VISIBLE);
slide_down(MainActivity.this, infoLayout);
}
}
}
public static void slide_down(Context ctx, View v){
Animation a = AnimationUtils.loadAnimation(ctx, R.anim.slide_down);
if(a != null){
a.reset();
if(v != null){
v.clearAnimation();
v.startAnimation(a);
}
}
}
public static void slide_up(Context ctx, View v){
Animation a = AnimationUtils.loadAnimation(ctx, R.anim.slide_up);
if(a != null){
a.reset();
if(v != null){
v.clearAnimation();
v.startAnimation(a);
}
}
}
}
The thing is that I tried to debug the code and it getting into the onclick function but nothing is happening - the layout that is gone not been shown.
I've chacked the animation code with simple textview outside the listview and it worked, but when im trying to use it in the listview item, it doesn't work.
Any ideas why?
Thanks for any kind of help
Use ExpandableListView. You have to extend the BaseExpandableListAdapter to your adapter and override methods. In this methods, override getGroupView to display the name of expandablegroup and override getChildView method to inflate the child view for list. After inflating the layout for child, set whatever animation you want on that view.
you shoud use expandableview for it...
basic example fot that is here... expandavlelistview example
I have an inflated Linear Layout that contains 2 TextViews inside it.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="vertical" >
<TextView
android:id="#+id/tv_m"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/ll_borders"
android:tag="m"
android:text="m" />
<TextView
android:id="#+id/tv_q"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/ll_borders"
android:tag="q"
android:text="q" />
</LinearLayout>
All i want is that when this Linear Layout is inflated then i want to get the only TEXTVIEW on which i click. For example if i click on "tv_m" then it shall only return me the text of tv_m.
May b its simple but i am not getting a way to it. So i need help.
Thanks
After inflating the layout get the textview objects as below
LinearLayout layout = inflater.inflate(<your layout name>, null);
TextView textView1 = layout.findViewById(R.id.tv_m));
TextView textView2 = layout.findViewById(R.id.tv_q));
String selectedText;
textView1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
selectedText = textView1.getText().toString();
}
});
Similarly you can put listener for textView2 also. The selectedText will be the final string which you want.
You need to set up on click listeners for the text views. Then when one is clicked, it will call a function in your code passing it the view that was touched. Then you can call getText on it.
here is the code just check this out :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout lt = (LinearLayout) findViewById( R.id.linearLayout );
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(your xml to be inflate, null, false);
lt.addView(view);
TextView tv_m = (TextView)view.findViewById( R.id.tv_m);
TextView tv_l = (TextView)view.findViewById( R.id.tv_l);
tv_m.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tv_m.getText(); // to get the value written on text view
} });
}
I am using a XML-layout which I am prompting as the dialog box.
Designing of XML-layout is well formatted with enough required height and width..
But when I open it as the dialog box its width is getting disturbed so how to set height and width of dialog box through coding.
I even had referred this previous STACK OVERFLOW QUESTION
Here is the code:
// Layout Inflater Code..
editDialog = new Dialog(this);
layoutEdit = LayoutInflater.from(this).inflate(R.layout.createlayout, null);
//layoutEdit.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
editDialog.setContentView(layoutEdit);
// Called the Dialogbox to inflate
updateButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
editDialog.show();
}
});
// XML File Code:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/bd"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:freezesText="false"
android:text="Enter Name"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/whtie"
android:typeface="monospace" />
<EditText
android:id="#+id/txtname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName" >
</EditText>
</LinearLayout>
</ScrollView>
Try this...
1.Dialog snippet:
private void CustomDialog(String msg) {
final Dialog dialog = new Dialog(YourActivity.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
LinearLayout.LayoutParams dialogParams = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, 300);//set height(300) and width(match_parent) here, ie (width,height)
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View dislogView = inflater
.inflate(R.layout.my_custom_popup, null);
dialog.setContentView(dislogView, dialogParams);
TextView popupMsg = (TextView) dialog.findViewById(R.id.popupMsg);
Button popupOk = (Button) dialog.findViewById(R.id.popupOk);
popupMsg.setText(msg);
popupOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
2.Then call CustomDialog(Str) where you want to prompt in your activity.
CustomDialog("This is customized popup dialog!");
You better use an activity that looks like a dialog (I feel it will be better in your case). Here is an example code:
public class DialogActivity extends Activity {
/**
* Initialization of the Activity after it is first created. Must at least
* call {#link android.app.Activity#setContentView setContentView()} to
* describe what is to be displayed in the screen.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
// Be sure to call the super class.
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
// See assets/res/any/layout/dialog_activity.xml for this
// view layout definition, which is being set here as
// the content of our screen.
setContentView(R.layout.dialog_activity);
getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
android.R.drawable.ic_dialog_alert);
}
}
This code is from api demos
View layout = inflater.inflate(R.layout.view, NULL);
layout.setMinimumWidth(200);
layout.setMinimumHeight(200);
dialog.setContentView(layout);
Try
dialog.getWindow().setLayout(height, width);
Sorry if this redundant with the ton of questions/answers on inflate, but I could not get a solution to my problem.
I have a compound view (LinearLayout) that has a fixed part defined in XML and additional functionalities in code. I want to dynamically add views to it.
Here is the XML part (compound.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/compoundView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView android:id="#+id/myTextView"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="000" />
</LinearLayout>
I have defined in code a LinearLayout to refer to the XML:
public class CompoundControlClass extends LinearLayout {
public CompoundControlClass (Context context) {
super(context);
LayoutInflater li;
li = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
li.inflate(R.layout.compound_xml,*ROOT*, *ATTACH*);
}
public void addAView(){
Button dynBut = new Button();
// buttoin def+layout info stripped for brevity
addView(dynBut);
}
}
I tried to programmatically add a view with addAView.
If ROOT is null and ATTACH is false, I have the following hierarchy (per HierarchyViewer):
CompoundControlClass>dynBut
The original TextView in the XML is gone.
If ROOT is this and ATTACH is true, I have the following hierarchy:
CompoundControlClass>compoundView>myTextView
CompoundControlClass>dynBut
I would like to have
CompoundControlClass>myTextView
CompoundControlClass>dynBut
where basically the code and XML are only one unique View.
What have I grossly missed?
ANSWER BASED on feedback from D Yao ----------------------
The trick is to INCLUDE the compound component in the main layout instead of referencing it directly.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/comound"
android:id="#+id/compoundView"
android:layout_alignParentBottom="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
mainActivity.java
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CompoundControlClass c = (CompoundControlClass) this.findViewById(R.id.compoundView);
c.addAView(this);
}
}
CompoundControlClass.java
public class CompoundControlClass extends LinearLayout {
public CompoundControlClass(Context context) {
super(context);
}
public CompoundControlClass(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CompoundControlClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void addAView(Context context){
ImageView iv = new ImageView(context);
iv.setImageResource(R.drawable.airhorn);
addView(iv);
}
}
compound.xml
<com.sounddisplaymodule.CompoundControlClass xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/compoundView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="110dp"
android:layout_height="wrap_content"
android:gravity="right"
android:textSize="40sp"
android:textStyle="bold"
android:text="0:00" />
</com.sounddisplaymodule.CompoundControlClass>
Why not just call addView on the linearlayout? I don't see the need for CompoundControlClass based on the needs you have listed.
LinearLayout v = (LinearLayout)findViewById(R.id.compoundView);
v.addView(dynBut);
In this case, v will contain myTextView, then dynBut.
if you wish to have other functions added and thus really feel a need for creating the compound control class, just leave the constructor as super(etc) and remove the rest
Then your xml would look like this:
<com.yourpackage.CompoundControlClass xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/compoundView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView android:id="#+id/myTextView"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="000" />
</com.yourpackage.CompoundControlClass>
you will also have to ensure your CompoundControlClass.java contains the appropriate Constructor which takes both a Context and an attribute set.
Then, in your java, after you've called setContentView, you can do the following:
CompoundControlClass c = (CompoundControlClass)findViewById(R.id.compoundView);
Button b = new Button(context);
//setup b here or inflate your button with inflater
c.addView(b);
this would give you your desired heirarchy.
I'm struggling with a problem for a few days already and couldn't find solution to my problem so far.
I have two classes:
- StartActivity extends Activity
- TimeGraphView extends SurfaceView
What I want to achieve is to add dynamically buttons from within TimeGraphView to another view (LinearLayout).
To do so wanted to get that LinearLayout inside TimeGraphView with findViewById() but it returns null, and it should because I call it in TimeGraphView not in root element where I used setContentView();
So my question is how can I add button dynamically from custom view level to another view.
And my code:
public class StartActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.time_graph);
LinearLayout layout = (LinearLayout) this.findViewById(R.id.TimeGraphLayout);
//here I can add button but it's not what I want
}
}
and ...
public class TimeGraphView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
public TimeGraphView(Context context) {
super(context);
}
public TimeGraphView(Context context, AttributeSet set) {
super(context, set);
}
public TimeGraphView(Context context, AttributeSet set, int arg) {
super(context, set, arg);
}
public void run() {
while (run) {
if (something) {
LinearLayout layout = (LinearLayout) findViewById(R.id.TimeGraphLayout);
if (layout != null) {
Button button = new Button(context);
button.setText(text);
layout.addView(button);
} else {
Log.e("TimeGraphView", "TimeGraphLayout is null");
//and "layout" is always null and that's the problem ;(
}
}
}
}
}
... and my XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/TimeGraphRootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<HorizontalScrollViewa
android:id="#+id/TimeGraphPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/TimeGraphLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</HorizontalScrollView>
<my.package.TimeGraphView
android:id="#+id/TimeGraphChart"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
You cannot use it in that way. If you add a root element Linearlayout and reference that in addition it might work. If you want to get the TimeGraphLayout class though:
TimeGraphView layout = (TimeGraphView) findViewById(R.id.TimeGraphLayout);
setContentView(layout);
The original way you did it will not work because TimeGraphView is not a LinearLayout