Setting layout of a CustomView based on user input - android

I have a custom view extending the RelativeLayout. In the init(Context context, AttributeSet attrs) method of this class I set the layout file by:
inflate(getContext(), R.layout.in_session_view_layout, this);
I am using this custom view in a list item like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:verizon="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_margin="5dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageView
android:id="#+id/flag"
android:layout_width="60dp"
android:layout_height="160dp"
android:layout_below="#id/txt"
android:layout_gravity="center"
android:layout_margin="5dp" />
</FrameLayout>
<com.widgets.FreeBeeNotificationView
android:id="#+id/freebee_pre_session_view"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_gravity="right|top"
android:layout_marginBottom="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="6dp"
verizon:textSize="12sp" />
</FrameLayout>
Now, the requirement is that, this layout file needs to be set in the custom view dynamically based on an user input. But, I receive the user input after the init() method of the custom view has already been called as this method gets called as soon as the FrameLayout given above gets loaded.
How do I dynamically set the layout file to the custom view based on user input? Can someone kindly help me.
Thanks.

Hope I have understood your requirement correctly. If not please explain further.
You can do this.
In your custom view make a method called setLayout(int layoutId)
public void setLayout(int layoutId)
{
removeAllViews();
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(getContext(), layoutId, this);
}
When you have your user input you call
yourCustomView.setLayout(R.layout.new_layout);
Disclaimer: All this is from memory and not tested so might not compile.

Related

How to make my own XML layout view from other views

I have one RelativeLayout that has TextView (first label) , EditText(for input), TextView (second label). I have this in at least 10 activities in my project. How I can extract view and make my own. So, if I want to change textSize , I will have to change it on just one place, not 10.
For example I would like to have this
<RelativeLayout
android:width="match_parent"
android:height="wrap_content"
>
<TextView
android:id="firstTextView"
...
android:text="I like">
<EditText
android:id="edittextColor"
hint="type some color here"
... >
<TextView
android:id="secondTextView"
...
android:text="car.">
</RelativeLayout>
So, I need something like this on a lot of place. What I would like to have is:
<MySpecialView
firstText="I like"
colorEditTextHint="type color here"
secondText="car"/>
Inflaters
Let's suppose that your RelativeLayout file is called reusable_layout. This means that you could access it as R.layout.reusable_layout (considering that you have this file stored in the layouts folder of your project).
In your usual override of onCreate() add these variables at the start: LayoutInflater inflater = getSystemService(LAYOUT_INFLATER_SERVICE);
RelativeLayout layout = inflater.inflate(R.layout.reusable_layout, null);
Afterwards, call setContentView(layout);
If you want to edit the children you can call layout.getChildAt(int childNumber); This would return you a View
An example of editing the first TextView child:
TextView tv = (TextView) layout.getChildAt(0);
tv.setText("Example String");
UPDATE:
Another way to do what you want!
Creating a custom view may do the job!
A good tutorial on these is included here: https://developer.android.com/training/custom-views/create-view.html#subclassview
I think all you need to know is included in that.
Another possibly useful source would be included here: how to add views inside a custom View?
Hope I helped,
-Daniel
You can create one common layout and include in all the 10 activities layout like this
common_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/label1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Label1"/>
<EditText
android:id="#+id/input1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/label1"
android:text="Input1"/>
</RelativeLayout>
activity_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/common_layout"/>
<TextView
android:id="#+id/textinactivity_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Activity text"/>
</LinearLayout>
I hope this is what you wanted.
Although Android offers a variety of widgets to provide small and
re-usable interactive elements, you might also need to re-use larger
components that require a special layout. To efficiently re-use
complete layouts, you can use the include and merge tags to
embed another layout inside the current layout.
https://developer.android.com/training/improving-layouts/reusing-layouts.html
What about <include>
create you your_base_layout.xml and <include> it in any other xml in the place where you want to add it
your_base_layout.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/some_other_id">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/button1" />
</LinearLayout>
<include
android:id="#+id/include_id"
layout="#layout/your_base_layout" />
example of usage: another_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/app_bg"
android:gravity="center_horizontal">
<include
android:id="#+id/include_id"
layout="#layout/your_base_layout" />
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:padding="10dp" />
...
</LinearLayout>
This is how you access views in it,
View includedLayout = findViewById(R.id.some_id_if_needed);
Button buttonInsideTheIncludedLayout = (Button) includedLayout.findViewById(R.id.button1); // if there is a button in your base layout that you included access like this
find great answers >here
You can define your own control with specified attributes.
Save ButtonPlus.java into your package.
e.g.
public class ButtonPlus extends Button {
public ButtonPlus(Context context) {
super(context);
}
public ButtonPlus(Context context, AttributeSet attrs) {
super(context, attrs);
CustomFontHelper.setCustomFont(this, context, attrs);
}
public ButtonPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
CustomFontHelper.setCustomFont(this, context, attrs);
}
}
And you can use inside your layout XML file.

Custom ViewGroup with children inserted at specific spot

I have several Activities in my Android app that have the same basic structure, and I'm trying to make my layouts DRY. The duplicated code looks like the below. It contains a scrollable area with a footer that has "Back" and "Dashboard" links. There's also a FrameLayout being used to apply a gradient on top of the scrollable area.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ScrollView
android:layout_width="match_parent"
android:layout_height="689px">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- THE REAL PAGE CONTENT GOES HERE -->
</LinearLayout>
</ScrollView>
<ImageView
android:src="#drawable/GradientBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="50px"
android:background="?attr/primaryAccentColor">
<Button
android:layout_width="wrap_content"
android:layout_height="26px"
android:layout_gravity="center_vertical"
local:MvxBind="Click GoBackCommand" />
<Button
android:layout_width="wrap_content"
android:layout_height="26px"
local:MvxBind="Click ShowDashboardHomeCommand" />
</FrameLayout>
</LinearLayout>
To de-dupcliate my Activities, I think what I need to do is create a custom ViewGroup inherited from a LinearLayout. In that code, load the above content from an XML file. Where I am lost is how to get the child content in the Activity to load into the correct spot. E.g. let's say my Activity now contains:
<com.myapp.ScrollableVerticalLayoutWithDashboard
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- THE REAL PAGE CONTENT GOES HERE -->
<TextView android:text"blah blah blah" />
</com.myapp.ScrollableVerticalLayoutWithDashboard>
Now how do I cause the "blah blah blah" to appear in the correct place? I'm pretty sure if I did this, I would either end up with "blah blah blah" at the top or bottom of the page, not in the middle of the ScrollView as desired.
I'm using API 21 / v5.0+. Technically I'm doing all this with Xamarin, but hopefully that's irrelevant to the answer?
EDIT: An example of what the result would look like is this. The footer and gradient are part of the custom ViewGroup, but the rest would be content within the custom ViewGroup.
I don't know Xamarin so this is an native android solution, but should be easy to translate.
I think what I need to do is create a custom ViewGroup inherited from
a LinearLayout.
Yes, you could extend the LinearLayout class.
Where I am lost is how to get the child content in the Activity to
load into the correct spot.
In your custom implementation you need to handle the children manually. In the constructor of that custom class inflate the layout manually:
private LinearLayout mDecor;
public ScrollableVerticalLayoutWithDashboard(Context context, AttributeSet attrs) {
super(context, attrs);
// inflate the layout directly, this will pass through our addView method
LayoutInflater.from(context).inflate(R.layout.your_layout, this);
}
and then override the addView()(which a ViewGroup uses to append it's children) method to handle different types of views:
private LinearLayout mDecor;
public void addView(View child, int index, ViewGroup.LayoutParams params) {
// R.id.decor will be an id set on the root LinearLayout in the layout so we can know
// the type of view
if (child.getId() != R.id.decor) {
// this isn't the root of our inflated view so it must be the actual content, like
// the bla bla TextView
// R.id.content will be an id set on the LinearLayout inside the ScrollView where
// the content will sit
((LinearLayout) mDecor.findViewById(R.id.content)).addView(child, params);
return;
}
mDecor = (LinearLayout) child; // keep a reference to this static part of the view
super.addView(child, index, params); // add the decor view, the actual content will
// not be added here
}
In Xamarin you're looking for the https://developer.xamarin.com/api/member/Android.Views.ViewGroup.AddView/p/Android.Views.View/System.Int32/Android.Views.ViewGroup+LayoutParams/ method to override. Keep in mind that this is a simple implementation.
EDIT: Rather than putting a LinearLayout inside a LinearLayout, you could just use the 'merge' tag. Here's the final layout you'd want:
<?xml version="1.0" encoding="utf-8" ?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:id="#+id/svfFrame1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ScrollView
android:layout_width="match_parent"
android:layout_height="689px">
<LinearLayout
android:id="#+id/svfContentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="23px" />
</ScrollView>
<ImageView
android:src="#drawable/GradientBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</FrameLayout>
<FrameLayout
android:id="#+id/svfFrame2"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="50px"
android:background="?attr/primaryAccentColor">
<Button
android:id="#+id/FooterBackButton"
android:layout_width="wrap_content"
android:layout_height="26px"
android:layout_gravity="center_vertical"
android:layout_marginLeft="24px" />
<Button
android:id="#+id/FooterDashboardButton"
android:layout_width="wrap_content"
android:layout_height="26px"
android:layout_gravity="center_vertical|right"
android:layout_marginRight="24px" />
</FrameLayout>
</merge>
And here's the final working C# view for Xamarin based on that layout:
public class ScrollableVerticalLayoutWithDashboard: LinearLayout
{
public ScrollableVerticalLayoutWithDashboard(Context context, IAttributeSet attrs) : base(context, attrs)
{
LayoutInflater.From(context).Inflate(Resource.Layout.ScrollableVerticalFooter, this);
base.Orientation = Orientation.Vertical;
}
public override void AddView(View child, int index, ViewGroup.LayoutParams #params)
{
// Check to see if the child is either of the two direct children from the layout
if (child.Id == Resource.Id.svfFrame1 || child.Id == Resource.Id.svfFrame2)
{
// This is one of our true direct children from our own layout. Add it "normally" using the base class.
base.AddView(child, index, #params);
}
else
{
// This is content coming from the parent layout, not our own inflated layout. It
// must be the actual content, like the bla bla TextView. Add it at the appropriate location.
((LinearLayout)this.FindViewById(Resource.Id.svfContentLayout)).AddView(child, #params);
}
}
}

Android: onTouchListener in root view (RelativeLayout) isn't working

I'm developing an Android application and I'm trying to capture OnTouch events in my whole screen. All my activities will have a header with two buttons and then a body that's going to change.
In the Activity I'm testing right now the body is a ListView, so the Activity has:
-Two Buttons at the top of the screen.
-ListView under those two buttons.
I want to capture onTouchEvents in the whole screen. I tried setting an OnTouchListener to my root RelativeLayout and set clickable=false and focusable=false to all the other views, but it's not working: the onTouch event is only triggered when I click the first button.
This is my layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
tools:context=".MainActivity" >
<include
layout="#layout/header"
android:clickable="false"
android:focusable="false" />
<ListView
android:id="#+id/lvLocations"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/header_layout"
android:clickable="false"
android:focusable="false" />
</RelativeLayout>
This is the content of #layout/header:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/header_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:weightSum="5" >
<Button
android:id="#+id/homeButton"
android:layout_width="0dip"
android:layout_height="50dp"
android:layout_marginRight="5dp"
android:layout_weight="4"
android:clickable="false"
android:focusable="false"
android:onClick="Home"
android:text="#string/home" />
<ImageButton
android:id="#+id/speechButton"
android:layout_width="0dip"
android:layout_height="50dp"
android:layout_weight="1"
android:clickable="false"
android:focusable="false"
android:onClick="ClickMediaButton"
android:src="#drawable/micro" />
</LinearLayout>
And this is the code I'm using:
findViewById(R.id.root).setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("MACT", "TOUCH!");
}
});
Like I said, my log shows TOUCH only when the homeButton is clicked. Why is that? What am I doing wrong?
Thank you!
Why not just create a custom view for your RelativeLayout that catches the touch event and then you can do whatever you want with it?
public class CustomRelativeLayout extends RelativeLayout{
CustomRelativeLayout(Context context, AttributeSet attrs){
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent ev){
//handle touch event
return true;
}
}
You would then use this relative layout in your XML by looking for that class in your projects namespace. You can of course add whatever modifiers you want but here's an example of what it looks like.
<com.example.whatever.your.project.CustomRelativeLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
Once you catch the touch you can do whatever you want with it. You can pass it to other activities, you can use it to call other methods, etc. For more on how to use custom views see this part of the android docs.
I finally managed to solve it, and to do it I redesigned my layout. Now instead of having a header and a ListView I just have a ListView in my layout:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/myList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Then I add the header layout to my ListView:
View header = (View)getLayoutInflater().inflate(R.layout.header,null);
mList.addHeaderView(header);
Now I set the onTouchListener to the ListView and voilĂ , I receive the onTouch events in the whole screen.
I know this is a restrictive solution and it can't be used with complex layouts, but I can use it in the screens I needed it.

Hide row from ListView without taking up space

I have a ListView with an associated ArrayAdapter that displays its contents in several activities. Unfortunately it got necessary now, that my ListView in one of the settings does not display all its elements, but just the ones where "property" is not set to true. I would like to avoid to use two ArrayAdapters with different content, since then I somehow need to keep them in sync. I tried it like this (this method now just assumes that getView is called in the setting where we want to hide certain elements):
public View getView(int position, View convertView, Context context) {
....
if(!arrayitems[position].isProperty()) { //arrayitems is the underlying array
convertView.setVisibility(View.VISIBLE);
}
else {
convertView.setVisibility(View.GONE);
}
return convertView;
}
This works, however I get a white row if the element has isProperty == true. I would like to make the row invisible in the sense, that it does not take up any space anymore. Is that possible?
The used xml file for convertView looks like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text_item_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="4dp"
android:maxLines="1"
android:ellipsize="none"
android:textSize="12sp"
android:textStyle="bold" />
<TextView
android:id="#+id/text_item_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
<TextView android:id="#+id/text_item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:maxLines="3"
android:ellipsize="none" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:orientation="horizontal" >
<TextView
android:id="#+id/text_item_rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="4dp"
android:textSize="10sp" />
<TextView
android:id="#+id/text_item_voted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
I tried to replay all android:layout_height="wrap_content" with "fill_parent" but it did not change anything...
Thanks!
Set the Visibility of all the contents of the list view to GONE and then set the visibility of the View to Gone.... this will hide the row without occupying space..... it worked for me even i have been searching for this but after a research i found this....
EDIT 1 :
Setting the visibility of the View to GONE is enough. No need to set the child element's visibility.
I'm having same problem as you've
I've figured it out by inflating another layout layout with no height and width
Adapter.java
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (YOUR_CONDITION) {
return inflater.inflate(R.layout.blank_layout, parent,
false);
} else {
View vi = inflater.inflate(R.layout.list_item, parent, false);
return vi;
}
}
And blank layout will be like this,
blank_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical" >
</LinearLayout>
So what Romain meant was to add an id to your LinearLayout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:orientation="vertical"
android:id="#+id/linear_layout">
Then in your Java you would do
public View getView(int position, View convertView, Context context) {
....
holder.lLayout = (LinearLayout) convertView.findViewById(R.id.linear_layout);
....
if(!arrayitems[position].isProperty()) { //arrayitems is the underlying array
holder.lLayout.setVisibility(View.VISIBLE);
}
else {
holder.lLayout.setVisibility(View.GONE);
}
return convertView;
}
You may need to change it a bit if your inflating your views differently. I've done this myself and it works really well.
You can use the getview layout of android:layout_height="wrap_content" and do use Visibility gone to hide your layout
Another user had the same problem and he solved it this way: https://stackoverflow.com/a/7928923/1548679 .
I hope this could help you.
Greets
By modifying getCount() and also the position in getView() with your logic you can make it work for sample Check http://www.sherif.mobi/2012/01/listview-with-ability-to-hide-rows.html by #sherif-elkhatib

findViewById(int) returns null for custom views, but not Android built-ins

The Situation: I have some custom components in my layout. I have a common layout frame that I load in my Activity base class's onCreate(), and then load my content layouts in my implementations using an inflater, setting the root to the content column of the main layout.
The Problem: When I grab a reference to the Views, to actually extract the user's input, Activity.findViewById() returns null. It is perhaps a clue that the CheckBox and Button I have in the layout do NOT return null; I get a valid reference to the widget.
Things I've Tried: I know I am properly loading and inflating the layout xml, because everything shows up, and the standard Views in the same layout can be found by ID. I can interact with my Views and put content into them and everything, but I can't get a reference to them in my code.
I have tried cleaning the project, multiple times. R.id is fresh and up-to-date.
I have checked the Console and Error Log, and there's no UI/XML errors reported.
I tried getting a handle to the root layout of the content I loaded for this activity, and calling View.findViewById() to get my references, and that returns null, too. If I examine the layout in the debugger, I can drill down and find my Views in mChildren.
Perhaps another clue:
public VideoChooser(Context pCtxt, AttributeSet pAttrs)
{
super(pCtxt, pAttrs);
Log.d("VideoChooser", "Expected ID: " + R.id.vchShareVids + " | actual: " + getId());
}
will result in the following output:
DEBUG/VideoChooser(10372): Expected ID: 2131296271 | actual: 268435456
The ID assigned to the View doesn't match the ID in R.id! Why would that be? I know it's loading the android:id attribute, or else it would be -1 (View.NO_ID).
The Common Layout Frame:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res/com.foo"
android:id="#+id/common_frame" android:orientation="vertical"
android:layout_width="match_parent" android:layout_height="match_parent">
<!-- top banner -->
<LinearLayout android:id="#+id/frame_header" android:orientation="horizontal"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_marginBottom="16dp">
<ImageView android:src="#drawable/banner"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_weight="1" />
</LinearLayout>
<!-- content column -->
<LinearLayout android:id="#+id/frame_content" android:orientation="vertical"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginLeft="32dp" android:layout_marginRight="32dp" />
</LinearLayout>
The Content Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res/com.foo"
android:id="#+id/content_panel" android:orientation="vertical"
android:layout_width="match_parent" android:layout_height="match_parent">
<com.foo.view.VideoChooser android:id="#+id/vchShareVids"
foo:prompt_text="#string/prompt_share_vid" foo:prompt_size="16dp"
foo:preview_height="80dp"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginBottom="12dp" android:hapticFeedbackEnabled="true" />
<com.foo.view.ContactChooser android:id="#+id/cchRecipients"
foo:prompt_text="#string/prompt_share_email" foo:prompt_size="16dp"
foo:preview_lines="3" foo:dialog_title="Pretend you are picking contacts"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginBottom="12dp" android:hapticFeedbackEnabled="true" />
<com.foo.view.TextChooser android:id="#+id/tchDescription"
foo:prompt_text="#string/prompt_share_description" foo:prompt_size="16dp"
foo:preview_lines="1" foo:dialog_title="#string/title_msg_chooser_dlg"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginBottom="12dp" android:hapticFeedbackEnabled="true" />
<CheckBox android:id="#+id/chkReshare" android:text="#string/prompt_reshare"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:checked="true" android:hapticFeedbackEnabled="true" />
<Button android:id="#+id/btnSend" android:text="#string/btn_send"
android:layout_width="#dimen/btn_width" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:hapticFeedbackEnabled="true" />
</LinearLayout>
Activity Base Class onCreate():
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.common_frame);
}
Activity Implementation onCreate():
#Override
protected void onCreate(Bundle pState)
{
super.onCreate(pState);
load_content_view(R.layout.content_layout);
ViewGroup tLayout = (ViewGroup)findViewById(R.id.content_panel);
// These all return null
mCchVideo = (ContentChooser)tLayout.findViewById(R.id.vchShareVids);
mCchContact = (ContentChooser)tLayout.findViewById(R.id.cchRecipients);
mCchDescription = (ContentChooser)tLayout.findViewById(R.id.tchDescription);
// These return valid references
mChkReshare = (CheckBox)findViewById(R.id.chkReshare);
mBtnSend = (Button)findViewById(R.id.btnSend);
// ...
}
protected void load_content_view(int pResId)
{
LinearLayout tColumn = (LinearLayout)findViewById(R.id.frame_content);
getLayoutInflater().inflate(pResId, tColumn);
}
I had a similar problem and the solution for mine was to make sure the constructor of the custom widget calls
super(context, attrs);
My constructor didn't pass attrs to super and thus the view id was messed up and the findviewbyId returned null.
It's very difficult to find problem without actual sources. I've created sample project based on your posts and its fully works.
I believe that there is very simple mistake and you'll find it.
If you want, you may try it
Yeah... I'm an idiot. View was of course setting the correct ID, and then one of my init methods went back and clobbered it.
facepalm

Categories

Resources