I have a layout that contains a TextView that looks like this
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/visual_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor=?android:attr/colorAccent
android:maxLines="3"
android:gravity="center_vertical" />
I have specified an overlay directory and I'm attempting to overlay the layout file using a similar file except with some minor differences
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/visual_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor=?android:attr/colorPrimary
android:maxLines="3"
android:gravity="top" />
My application builds successfully, however, I'm seeing a NullPointerException during runtime when my Java code tries to set the text of the TextView
private void setVisualText(View someView) {
View view = getLayoutInflater().inflate(R.layout.myLayout, someView, false);
TextView myText = (TextView)view.findViewById(R.id.visual_text);
myText.setText(R.string.myString);
}
The exception happens only with the overlay file and the code runs fine without the overlay. Does anyone know why myText is null and why it's not finding the view correctly? My guess is it's related to the ID but I'm not sure why it's not resolving correctly.
So you have a TextView and an overlaying TextView?
If so, you should not use the same ids. Ids should be used only once.
Why are you calling?
getLayoutInflater().inflate(R.layout.myLayout, someView, false);
If you want to get a view from the main contentView, you can just use:
findViewById(id);
because if you want to attach the inflated view to the root you have to call:
getLayoutInflater().inflate(R.layout.myLayout, someView, true);
please try it with (..true).
by using the line above, you are getting the contentView view.
Related
I'm getting frustrated about this:
When I define a custom ListView Layout,
Android Studio doesn't keep the background drawable I set in there.
Tried many things, and setting background programmatically doesn't work
since it's ignoring the layout_width which must be set to "wrap_content".
Actual style of background
Result without coding
If anyone could help me, I'd be very grateful !:)
EDIT:
I'm creating a Messenger and I want to display messages in a similar way to WhatsApp, where messages are shown in a listView. Depending on message is sent or received, items should be aligned ParentStart or ParentEnd.
But more importantly, if a message only contains a few chars, I don't want the ListItem Background to fill the entire screen, so it should be set dynamically.
I thought I could achieve this through simply setting wrap content in the parent layout file.
Files look like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentEnd="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
tools:background="#drawable/background_message_sent">
//Here are TextViews
</LinearLayout>
</RelativeLayout>
Here is my ListViewAdapter, where I set background
(#drawable/background_message_sent/received) programmatically.
However, this covers the entire width of ListView, regardless of message length.
#Override
public View getView(int pos, View convertView, ViewGroup parent) {
int currentUserID = 1;
int senderID = messagesArrayList.get(pos).getSenderID();
if (senderID == currentUserID){
View v = View.inflate(context, R.layout.layout_chat_message_sent, null);
v.setBackgroundResource(R.drawable.background_message_sent);
TextView tvMessageText = v.findViewById(R.id.tvMessageText);
TextView tvTimeStamp = v.findViewById(R.id.tvTimeStamp);
tvMessageText.setText(messagesArrayList.get(pos).getMessageText());
tvTimeStamp.setText(messagesArrayList.get(pos).getTimeStamp());
return v;
}
else {
View v = View.inflate(context, R.layout.layout_chat_message_received, null);
v.setBackgroundResource(R.drawable.background_message_received);
TextView tvMessageText = v.findViewById(R.id.tvMessageText);
TextView tvTimeStamp = v.findViewById(R.id.tvTimeStamp);
tvMessageText.setText(messagesArrayList.get(pos).getMessageText());
tvTimeStamp.setText(messagesArrayList.get(pos).getTimeStamp());
return v;
}
}
Well, after trying, I got the solution if anyone comes to this point:
You have to set your background drawable directly for each TextView, not for Parent Layouts.
These two Lines finally solved everything ^^
android:maxEms="14"
android:background="#drawable/background_message_sent"
<TextView
android:id="#+id/tvMessageText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginEnd="0dp"
android:layout_marginTop="5dp"
android:layout_weight="0.22"
android:text="42456456456546"
android:textColor="#color/tentakelPrimary"
android:maxEms="14"
android:background="#drawable/background_message_sent"/>
I have a layout as below:
Let's name it my_layout.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="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="#ffffff"
android:background="#19396a"
/>
<TextView
android:id="#+id/textView2"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="#ffffff"
android:background="#19396a"
/>
</LinearLayout>
<ListView
android:id="#+id/uilistView"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
In my activity I have a method in which I initialize all the UI elements i.e I do mapping of activity UI variables to layout.
Assume, the method is as below:-
//used to initialize UI elements
//called in oncreate() method
public void initializeUIelements() {
......
activity_listView = (ListView) findViewById(R.id.uilistView);
}
Here, activity_listView is a class level variable of type ListView
In my project, I have res\layout as well as res\layout-land and my_layout.xml exists in both the folders.
But sometimes during activity restart/when it's created I get a NullpointerException while initializing activity_listView that comes from R.java.
I know:
We get NullpointerException similar to what I am asking when an
element does not exist in any of the layout folder(i.e it exists in layout-land but does not exist in layout folder).
But here,the element exists in both folders and even though I get this inconsistent error
i.e. I am not able to produce it always but sometimes it starts coming.
So,please help me in analyzing as what may be the reasons when we get this error apart from the one mentioned by me above.
Thanks in advance.
If you could provide a more specific example, it might be easier to debug the exact problem. A few reasons why your View might be null:
The layout you've set as the content view does not include a view with this id:
If you reference a View that exists in the R file (a file that holds references to all elements within the res folder), say uilistview, in an Activity where you are not setting it's layout container as the content view (in this case this would be my_layout.xml), you will not get an error in Eclipse or whatever IDE you are using. Android will look for a View with this id within the layout, and if it can't find it, it will return a null value.
You call findViewById too early
You must use the method setContentView(R.layout.some_layout) before you try to access any of the elements with findViewById(). Logically, it makes sense - you need to tell Android where it should look where it's find an element
Looking for an element inside an inflated View
This is similar to the first, but it's common. If you've inflated a view and then want to manipulate a View inside the inflated View, you must instruct Android to look in the right place. For example:
RLayoutInflater layoutInflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View smallerView = layoutInflater.inflate(R.layout.mylayout);
If you want to reference something within mylayout.xml, you would need to use this:
TextView text = (TextView) smallerView.findViewById(R.id.text_view);
rather than:
TextView text = (TextView) findViewById(R.id.text_view);
The first indicates to look into the inflated view by placing the findViewById method on the inflated view, while the second one applies it to the current View of the Activity, which will cause a null value to be return.
Clean your project
This is the most frustrating answer, because this is not your fault. Sometimes the R.java class messes up and causes wrong references to id's while it is being compiled/built. Try cleaning your project and correcting the wrong references by looking for Project -> Clean in the main bar of Eclipse (or the IDE you're using).
I have one xml file main_layout.xml and in this I have another xml layout popup_layout.xml which is added by :
<include
android:id="#+id/popup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
layout="#layout/popup_layout" />
In the file MainActivity.java I would like to get the popup object so I can change it's textfields etc. What do i write?
I've tested
View v = findViewById(R.id.popup);
TextView tv= (TextView) v.findViewById(R.id.ip_answer);
but it doesn't work
The id attribute for include is not required. Add id attribute to the layout you want to include , then find view by that id an collect it accordingly as the type of layout
eg:
RelativeLayout/LinearLayout= findViewById(id);
then find the text view .
This should work
I am attempting to write code that would allow me to have 1-2 views at the top of a listview that are of a different arrangement than the other views in the listview. I decided to try the method of using addHeaderView() for the 1-2 views that will differ in display.
I have two xml layout files, one that defines the view format that most of the listview views will fall under (list_image_checkbox_row.xml) and one for the Header Views (catalog_featured_row.xml). The adapter constructor uses list_image_checkbox_row as its resource in the constructor.
I used a Thread to set the adapter and load the views. I am able to programmatically create views and use addHeaderView to at them to the listview (using the same image resource), but I get errors when I try to use addHeaderView on a view I have inflated from a layout xml file.
handler.post(new Runnable() {
#Override
public void run() {
lv = (ListView)findViewById(R.id.sources_list);
Activity context = BrowseSourceActivity.this;
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.catalog_featured_row, null);
ImageView feat_view = (ImageView) view.findViewById(R.id.image);
feat_view.setImageResource(R.drawable.arrow);
lv.addHeaderView(feat_view);
setListAdapter(array);
}
});
I get a force close error and haven't been able to find anything in logcat (when I was trying to debug yesterday I got a NullPointerException). If I comment out the lv.addHeaderView(feat_view) line, the application does not force close on me. Here is the code for featured_catalog_row.xml:
<?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="70dip"
android:padding="5dip">
<ProgressBar android:id="#+id/spinner"
android:indeterminate="true"
android:layout_width="30dip"
android:layout_height="30dip"
android:layout_centerInParent="true"
/>
<ImageView android:id="#+id/image"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
Any suggestions for how to get the inflater to work?
Perhaps you should store lv in an instance variable instead of looking it up dynamically. Note that both View and Activity have a method called findViewById, and so your results will depend on how your code is organized.
I just didn't want to use ScrollView. So I have a textview with enabled vertical scrollbars.
<TextView
android:id="#+id/tv_service_ticketinfo_details"
android:layout_width="fill_parent"
android:layout_height="150dp"
android:textColor="#color/black"
android:autoLink="web"
android:scrollbars="vertical"
android:text="empty"
android:background="#drawable/custom_shape_grey">
</TextView>
The problem is, that scrollbars are scrollable only for texts, which contain a web-links. For other texts I see a scrollbar, but can't scroll.
I can't explain it. And you?
UPD:
Another strange thing:
once I set the text with links, then I can replace it by another one without links and the textView stays scrollable
So I think the problem is that TextViews don't automatically scroll, just because you set android:scrollbars. You have to set the ScrollingMovementMethod.
However, when you use autoLink and links are found, the android framework will set the MovementMethod for you. That's why the behaviour's different.
There are two solutions that work for me.
After we set our text, force the movement method to one that supports links and scrolling.
final TextView output = (TextView) findViewById(R.id.output);
output.setText(content);
// ensure that text will scroll with or without linked text
output.setMovementMethod(LinkMovementMethod.getInstance());
Or set the movement method, assuming plaintext, before adding text to the TextView. If autoLink detects links, it will change the movement method itself.
final TextView output = (TextView) findViewById(R.id.t_output);
// ensure that text defaults to scrollable
output.setMovementMethod(ScrollingMovementMethod.getInstance());
output.setText(content);
(FYI: I'm using android:autoLink="all")
add this in your code(may be in onCreate)
//textView.setMovementMethod(ScrollingMovementMethod.getInstance());
tv_service_ticketinfo_details.setMovementMethod(ScrollingMovementMethod.getInstance());
and test.
To get a scroll bar at run time or from code, you may try with following solution:
xml:
<LinearLayout
android:id="#+id/view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<TextView
android:id="#+id/tv_service_ticketinfo_details"
android:layout_width="fill_parent"
android:layout_height="150dp"
android:textColor="#color/black"
android:autoLink="web"
android:scrollbars="vertical"
android:text="empty"
android:background="#drawable/custom_shape_grey">
</TextView>
</LinearLayout>
java:
mTextViewPort = (LinearLayout) findViewById(R.id.view1);
// Create a ScrollView instance
ScrollView mScrollView = new Scrollview(mContext);
// here mContext would be Activity's context. You may also choose
// mScrollView as a global variable.
mScrollView.setScrollBarStyle(SCROLLBARS_OUTSIDE_INSET);
mTextViewPort.addView(mScrollView,
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
TextView mTextView = (TextView) findViewById(R.id.tv_service_ticketinfo_details);
mScrollView.addView(mTextView );
This may help to resolve this problem.