Android: findViewById is returning null? - java

In my main activity I'm trying to access a LinearLayout I have within my main ScrollView. My ScrollView is implemented as follows:
<?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">
<LinearLayout
android:id="#+id/graph"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="250dip"
/>
</ScrollView>
In my Main activity I inflate the scrollView and then try to access the linear layout as follows:
LayoutInflater inflater;
inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ScrollView mainLayout = (ScrollView) inflater.inflate(R.layout.scrollview,
null);
LinearLayout layout = (LinearLayout) findViewById(R.id.graph);
Why would my findViewById be returning null here? I thought at first it was trying to find it before it had finished inflating, but I've tried having a while loop to wait for it to finish inflating, and this doesn't help either.

you have to give it the inflated layout
LinearLayout layout = (LinearLayout) mainLayout.findViewById(R.id.graph);

You can double check if specify the wrong layout in inflater.inflate() first.

Related

Can I convert a View to Layout?

In android, one can Inflate a Layout file and will get a View in return.
For Example:
LayoutInflater layoutInflater = LayoutInflater.from(context);
View myView = layoutInflater.inflate(R.layout.example_layout, null);
But I'm trying if I can get a Layout back from that inflated layout which is now a View?
Something by which I can retrieve back the original Layout from the Inflated View.
LayoutInflater layoutInflater = LayoutInflater.from(context);
LinearLayout myView = (LinearLayout)layoutInflater.inflate(R.layout.example_layout, null);
That's it!
Just be sure that the root view in your layout.example_layout is a LinearLayout or whatever layout you desire. Otherwise you'll have a ClassCastException
Every layout or ViewGroup extends View, that's why the inflate method returns a View, it's up to you then performing the right cast.
Consider the layout below. It has a text view only.
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/mediumTextSize"
android:textColor="#color/black_text_color"
/>
After inflation you can directly get the textView as its the only view contain in layout.
LayoutInflater inflater=LayoutInflater.from(this);
TextView view=(TextView)inflater.inflate(R.layout.temp,null);
Now consider the layout below .
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/txtName"
android:layout_width="match_parent"
android:layout_height="40dp"
android:textColor="#color/black_text_color"
android:textSize="#dimen/largeTExtSize" />
<TextView
android:id="#+id/csvName"
android:layout_width="match_parent"
android:layout_height="40dp"
android:textColor="#color/black_text_color"
android:textSize="#dimen/largeTExtSize" />
</LinearLayout>
On inflation.
LayoutInflater inflater=LayoutInflater.from(this);
View view=inflater.inflate(R.layout.temp,null);
//Or you can do
// LinearLayout view=(LinearLayout)inflater.inflate(R.layout.temp,null);
TextView txt=view.findViewById(R.id.txtId);

Android darken background

Does anyone know how to programmatically darken a View's background like alertDialog or NavigationDrawer doing it? I need the background overlaps the ToolBar (1) and StatusBar, but the icons for the StatusBar should be visible(2). In my case it should not be a dialog. For example, I had to darken the background around the Button or CustomView.
Example Image
I was looking for the answer to this question for a long time, but finally I found a solution.
I researched code "DialogPlus" library and find out what is the key point.
orhanobut/dialogplus
getWindow().getDecorView();
final LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
final View background = inflater.inflate(R.layout.frame, null);
final Animation a = AnimationUtils.loadAnimation(this, R.anim.in);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ViewGroup decorView = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
decorView.addView(background);
background.startAnimation(a);
}
});
background resoource file:
<?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">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:alpha="0.5"></FrameLayout>
</LinearLayout>

Show activity's view overlay FrameLayout with Fragment

I have the following activity:
<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"
tools:context="es.xxx.xxx.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#CCFF0000"
android:id="#+id/lyNetworkError">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="No hay conexión a internet"
android:textAlignment="center"/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container"/>
</RelativeLayout>
In its FrameLayout the app will load other fragments.
This is the onCreate code of activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Constants.setAppContext(this);
setContentView(R.layout.activity_main);
Log.d("LoadFragment", "1 "+ loadFragment);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainFragment()).commit();
}
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkStateReceiver, filter);
fragmentManager = getSupportFragmentManager();
lyNetworkError = (LinearLayout) findViewById(R.id.lyNetworkError);
}
The problem is that LinearLayout (That contains TextView) doesn't show (is posible that fragment render over LinearLayout, because if I remove getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainFragment()).commit(); the LinearLayout appears)
So, how can I show the LinarLayout over fragment (loaded inside FrameLayout)?
If the LinearLayout and your Fragments are displaying in the correct location on screen when each is shown individually, then you can simply reverse the order of of the FrameLayout and LinearLayout in your XML.
The problem is that RelativeLayout allows its children to overlap. The last item in the RelativeLayout will appear "above" or "on top" of other items in the layout. Since you haven't specified any layout constraints for your views, the RelativeLayout puts them both in the default position, which is the top left corner. Since your FrameLayout is set to fill the parent view's width and height, it will overlay everything else.
If you actually want the LinearLayout to appear above the FrameLayout, then you can use RelativeLayout's positioning properties (explained very well here) to position your views.
Specifically, you would be looking for something like this:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/lyNetworkError"
android:id="#+id/container"/>
The android:layout_below attribute tells the FrameLayout that you want it to always be below the view with ID lyNetworkError (below as with text on a piece of paper, not in 3-dimensional space).

List navigation (spinner) on the right side

I have tried so many tutorials, but I could not find article that would tell me how to create spinner in action bar (sherlock version), but on the right side.
Is there a way to do it? Do I need to create additional views and adapters? I just want to know easy way to create that spinner on the right side, nothing else, just it.
You'll need to create a custom layout for the view containing the spinner. Inflate and place it on the action bar and you're good to go.
Here you have some sample code for this(this is what you do inside your activity to initialize and place your layout on the action bar):
LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext().getSystemService(LAYOUT_INFLATER_SERVICE);
final View spinnerView = inflater.inflate(R.layout.layout_spinner, null);
Spinner spinner = (Spinner) spinnerView.findViewById(R.id.my_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.spinner_items_array, R.layout.spinner_item);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// Do whatever you want with your selected item. You can get it as: parent.getItemAtPosition(position);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_actionbar_logo));//set your actionbar logo
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE );
LayoutParams layoutParams = new ActionBar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
layoutParams.gravity = Gravity.RIGHT; // set your layout's gravity to 'right'
getSupportActionBar().setCustomView(spinnerView, layoutParams); //place your layout on the actionbar
Your layout should look something like this (layout_spinner.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" >
<Spinner
style="#style/Widget.Sherlock.Light.Spinner.DropDown.ActionBar"
android:id="#+id/my_spinner"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right" />
</LinearLayout>
Your array stored in a res folder (spinner_items_array):
<string-array name="spinner_items_array">
<item>Item1</item>
<item>Item2</item>
</string-array>
The spinner custom item (spinner_item.xml):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/cab_spinner_item"
style="?android:attr/spinnerItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textAlignment="inherit"
android:textColor="#android:color/white" /> <!-- Set whatever color you want for the text -->
And finally the drop-down list item (spinner_dropdown_item.xml):
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/spinnerDropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="48dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textAlignment="inherit"
android:textColor="#android:color/white" />
I hope this answer will help you!!
Good luck!

Wrapping a LinearLayout around a TextView

I have the following code that populates a ListView with a TextView in the XML Layout file. But if I try to wrap a LinearLayout around the TextView it crashes!
Code:
setListAdapter(new ArrayAdapter<MyData>(getApplicationContext(), R.layout.articlelist, items));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MyData d = items[position];
Bundle bundle = new Bundle();
bundle.putString("theArticleText", d.getText());
Intent newIntent = new Intent(getApplicationContext(), ArticleDetail.class);
newIntent.putExtras(bundle);
startActivityForResult(newIntent, 0);
}
});
Working XML:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" />
Non working XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" />
</LinearLayout>
Any ideas why this is happening??? Also what I want to do is add an icon next to each item in the list, am I heading in the right direction???
Cheers,
Mike.
If you want to use the more complex layout, you will have to change the constructor you use for the ArrayAdapter to a version that takes both the ID of a layout AND the ID of the TextView to insert the text. When your layout is just a single TextView, you can get away with the other version because you only need to reference one thing; but now you have to tell the adapter both the layout to inflate and which view inside the new layout to use.
You will also need to modify your layout so the TextView has a valid ID to reference:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" />
</LinearLayout>
Notice the android:id parameter attached to the TextView. Then in your Java code use this constructor:
new ArrayAdapter<MyData>(getApplicationContext(), R.layout.articlelist, R.id.textview, items)
This now properly tells the adapter where to place the string data is obtains from each item.
HTH
If you check the documentation for the ArrayAdapter you'll see that the constructor gets as second parameter a textViewResourceId, that's why it does not crash using the first xml.
By the way keep in mind that a TextView is a view, a LinearLayout is a ViewGroup.
If you want to use your own layout you must write a custom adapter.
Hope it will help!

Categories