In Android application,
I create a LinearLayout which contains a TableLayout which contains some rows and one of the rows contains a TextView called mText1
I set up a pop up window with this LinearLayout with mText1 setting as following :
mText1.getLayoutParams().height = OLD VALUE
Then when in the pop up window in one other row of the table a click on an ImageView happens by the user, I'd like to change the height of mText1 as following :
mText1.getLayoutParams().height = NEW VALUE
The problem is this will not take effect but when I type the following code, it takes effect:
mText1.setGravity(Gravity.CENTER)
Or if I type the following code instead of the previous one, it takes effect too:
mText1.setText("some value")
Why?
You need to call requestLayout() after changing the LayoutParams.
requestLayout()
Call this when something has changed which has invalidated the layout
of this view. This will schedule a layout pass of the view tree.
setGravity and setText are handling this for you.
I want to be able to display text (a bar if you will) at the bottom of my application dynamically to indicate if the the application is online or not (an endless issue for users currently). I don't need for this to have any action, but I do need it to be able to control it displaying or not based on them toggling between online and offline mode. So the split action bar is not what I am looking for.
Not enough reputation points to post an example. Doh. Here is the link:
Ugly example, look at bottom
Something simple is fine - I am good with XML based or dynamic (though I will also need to hide and show it dynamically).
Thanks!
Dynamic solution. Define your method that the activity will use to hide / display your bottom TextView (text bar?).
In your XML:
<TextView
android:id="#+id/text_bar"
...
...
android:visibility="gone"/>
In your activity:
public MyActivity extends Activity{
private TextView mTextBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity_xml);
...
...
mTextBar = (TextView) findViewById(R.id.text_bar);
}
public void updateVisibility(boolean visible){
int visibility = (visible) ? View.VISIBLE: View.GONE;
mTextBar.setVisibility(visibility);
}
}
Initially, the TextView (your text bar) has it's visibiity set to gone. Dynamically, when you want to show it call the updateVisibility(true) method to show it, and updateVisibility(false) to hide it.
Since I'm not sure how you are handling the check for the network status (in queries, in the onCreate, etc). I don't know what you intended to do for the TextView. If you need advice on how to position the TextView on the bottom of the screen I can provide example code for that as well.
Why is
TextView test = (TextView) findViewById(R.id.testTextView);
test.getText();
generating a null pointer exception? The id is correct, testTextView is correctly declared in my XML layout file.
The only reason for findViewById to return null if you are passing a valid id is that you are either setting the wrong content view (with setContentView) or not setting a content view at all.
I think you might have written setContentView(..) after defining the TextView. Reverse these, and it should work.
Change:
TextView test = (TextView) findViewById(R.id.testTextView);
.
.
setContetView(..)
To:
setContetView(..)
.
.
TextView test = (TextView) findViewById(R.id.testTextView);
You probably haven't called setContentView. You can only use findViewById to get elements of views that have already been inflated.
You could also use a layoutinflater to inflate the view, but that's probably not what you want.
Are you sure the TextView is set on the right XML?
For example if you're creating a Dialog that loads a custom XML, to get an element from that xml you have to mention it in dialog.findViewById(R.id.testTextView);
Like Falmarri said, the view has to be inflated.
I understand you solved it by creating a new project, but still thought to mention it for future users.
It can also be that you defined the activity in two files. For example layout and layout-v21 and some information like id is missing on one of them. So check all the activity's layouts
In my case, the layout was not finished inflating. Solved by adding a small delay before trying to access the TextView.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
TextView test = (TextView) findViewById(R.id.testTextView);
test.getText();
}
}, 100);
I struggled with this for a while and what I realized was, that, if you have more than one layout file version like:
"activity_one.xml" in "layout" folder and one in "layout - small" folder
Which I used for multiple phone layout support, the problem was that one of the TextViews was in both, with the exact same ID and everything, however the difference was that one was higher up in the hierarchy of views in the layout.
When I changed them to be in the same spot it worked.
(I know this is already answered, but maybe this helps someone out there. Very rare though.)
I have a ListView. The data behind it is fetched from the Internet, in sets of 10-30 items whenever the user scrolls all the way to the bottom. In order to indicate that it is loading more items, I used addFooterView() to add a simple view that displays a "Loading..." message and a spinner. Now, when I'm out of data (no more data to fetch), I want to hide that message. I tried to do:
loadingView.setVisibility(View.GONE);
Unfortunately, while that does hide the view, it leaves space for it. I.e. I end up with a big blank space where the "Loading" message used to be. How can I go about properly hiding this view?
I can't use removeFooterView() because I may need to show it again, in which case I can't call addFooterView() again because an adapter has already been set on the ListView, and you can't call addHeaderView() / addFooterView() after setting an adapter.
It seems that you are allowed to call addHeaderView() / addFooterView() after setAdapter() as long as you call one of those methods at least once before. That is a rather poor design decision from Google, so I filed an issue. Combine this with removeFooterView() and you have my solution.
+1 for the other two answers I got, they're valid (and arguably more correct) solutions. Mine, however, is the simplest, and I like simplicity, so I'll mark my own answer as accepted.
Try setting the footer's height to 0px or 1px before hiding it. Alternatively, wrap the footer view in a wrap_content height FrameLayout and hide/show the inner view, leaving the FrameLayout visible; the height should wrap properly then.
in my case addFooterView / removeFooterView() cause some artefacts.
And I found other solution. I used FrameLayout as FooterView. And when I want to add Footer I called mFrameFooter.addView(myFooter); and mFrameFooter.removeAllViews(); for remove.
FrameLayout frameLayout = new FrameLayout(this);
listView.addFooterView(frameLayout);
......
......
//For adding footerView
frameLayout.removeAllViews();
frameLayout.addView(mFooterView);
//For hide FooterView
frameLayout.removeAllViews();
The Droid-Fu library has a class designed for having a loading footer show and hide: ListAdapterWithProgress.
Works well in my project:
1.Add footer view first
mListView.addFooterView(mFooterView);
mListView.setAdapter(mAdapter);
2.Set visibility
mFooterView.setVisibility(View.GONE);
mFooterView.setPadding(0, 0, 0, 0);
3.Set invisibility
mFooterView.setVisibility(View.GONE);
mFooterView.setPadding(0, -1*mFooterView.getHeight(), 0, 0);
As #YoniSamlan pointed out, it can be achieved in a simple way. You have to specify
android:layout_height="wrap_content"
in the ViewGroup that contains the "Load More" button. Doesn't have to be FrameLayout, see below for a simple -working- example that uses a LinearLayout.
Both images show a screen that is scrolled all the way to the bottom. First one has a visible footer that wraps around the "load more" button. Second images shows that the footer collapses if you set button's visibility to GONE.
You can show again the footer (inside some callback) by changing the visibility:
loadMore.setVisibility(View.VISIBLE); // set to View.GONE to hide it again
Perform listView initialization as usual
// Find View, set empty View if needed
mListView = (ListView) root.findViewById(R.id.reservations_search_results);
mListView.setEmptyView(root.findViewById(R.id.search_reservations_list_empty));
// Instantiate footerView using a LayoutInflater and add to listView
footerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.load_more_footer_view, null, false);
// additionally, find the "load more button" inside the footer view
loadMore = footerView.findViewById(R.id.load_more);
loadMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
fetchData();
}
});
// add footer view to the list
mListView.addFooterView(footerView);
// after we're done setting the footerView, we can setAdapter
adapter = new ReservationsArrayAdapter(getActivity(), R.layout.list_item_reservations_search, reservationsList);
mListView.setAdapter(adapter);
load_more_footer_view.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="wrap_content">
<Button
android:id="#+id/load_more"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="9dp"
android:gravity="center"
android:layout_gravity="center"
android:background="#drawable/transparent_white_border"
android:textColor="#android:color/white"
android:text="#string/LOAD_MORE"/>
It should be a bug of Android.
You don't need to remove or add footer view dynamically. You just need to create an unspecified height parent Layout (either inflate it from an xml file or create it programatically) and then add your view which you want to hide or show into it.
And you can set the view, but NOT the parent Layout, to VISIBLE or GONE or something else now. It works for me.
Used
footer.removeAllViews();
This does not remove footer but flushes children.
You again have to repopulate children. Can check by
footer.getChildCount()<2
I also found that is possible call onContentChanged() (if you use ListActivity) to force recreate ListView if I need add HeaderView to them after setAdapter() call, but it is very ugly hack.
I have created a ListView that handles this. It also has an option to use the EndlessScrollListener I've created to handle endless listviews, that loads data until there's no more data to load.
You can see these classes here:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java
- Helper to make it possible to use the features without extending from SimpleListViewWithLoadingIndicator.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java
- Listener that starts loading data when the user is about to reach the bottom of the ListView.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java
- The EndlessListView. You can use this class directly or extend from it.
I have small hack way to resolve this problem for everywhere.
Put listview and footer view (just sub layout) in parent layout like LinnearLayout, remember that footerview below listview.
Controller this footer view gone and visibility like nomal view. And done!
first I am adding my footer to the listview,like this
listView.addFooterView(Utils.b);
Then on button click , I remove the view,
listView.removeFooterView(Utils.b);
I am adding the footer everytime when I am hitting the async,and theus the're no duplicate entry.I could aslo check for the count and so it like this,
if(listView.getFooterViewsCount() > 0){//if footer is added already do something}
When you want to remove the footer in ListView just call
listView.addFooterView(new View(yourContext));
It will add a dummy empty view which will not reserve any space
I'm trying to restore the background Color of a View.
I have several selectable Views. When the user clicks one of those Views, the following code is executed and the View becomes Yellow:
View newSelection, previousSelection;
...
if(previousSelection != null) {
previousSelection.setBackgroundColor(Color.BLACK); // problem here
}
newSelection.setBackgroundColor(Color.YELLOW);
However, I want to reset the color of the previously selected View. However, I do not know which color it was (I'm setting it to Color.BLACK in the above code). I was not able to find a getBackgroundColor or similar method in the View class. If I had it, I could save the previous color and just put it back when the new View is selected.
use View.getBackground(), it returns the current 'Drawable' background of the view which can then be used in View.setBackgroundDrawable()
View theView;
Drawable originalBackground;
...
originalBackground = theView.getBackground();
theView.setBackgroundColor(Color.YELLOW);
...
theView.setBackgroundDrawable(originalBackground);
I'm not sure exactly what you are trying to accomplish but perhaps a ColorStateList would come in handy here.
You can try setting the previous color as a tag of the view.
For example
View newSelection, previousSelection;
newSelection.setTag(Color.Green);
previousSelection.setTag(Color.Black);
if(previousSelection != null) {
previousSelection.setBackgroundColor((int)previousSelection.getTag());
}
newSelection.setBackgroundColor(Color.YELLOW);
I haven't tried the code if there is an error but the flow on how to implement is there.