I'm new to Android, and I'm having a problem with checkboxes and textviews not refreshing at runtime. The TextView has to change color from light gray to a lighter gray, and the Checkbox has to change the custom drawable that it has from red to green. I have tried the detach and attach the fragment but it shuts down and maybe I don't know where to put the detach and attach in the fragment. I have tried invalidate() and requestLayout(), and it shuts down there too. I tried having them in onCreateView() and maybe I shouldn't put them there. I don't have an activity with my fragment. Here are the images that I need to change. What it has in the preview window is the green custom checkbox drawables but at runtime they are the red custom drawables which is what they were before I changed them to green, and the TextViews are a lighter gray in the preview window but they are a darker gray at Runtime which is what they were before.
public class CheckListFragment extends Fragment{
private RelativeLayout fragment_checklist;
private Fragment fragment = new CheckListFragment();
private Checkbox chkStart, chkDownload;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_checklist, container, false);
fragment_checklist = (RelativeLayout) rootView.findViewById(R.id.fragment_checklist_gather);
chkStart = (CheckBox) rootView.findViewById(R.id.chkStarted);
chkDownload = (CheckBox) rootView.findViewById(R.id.chkDownloaded);
//tried to explicitly make it green but doesn't work.
chkStart.setButtonDrawable(R.drawable.custom_green_checkbox);
chkDownload.setButtonDrawable(R.drawable.custom_green_checkbox);
fragment.getView().invalidate(); // tried these
fragment.getView().requestLayout();// tried these
//tried this. Maybe in the wrong spot.
FragmentTransaction ft = getFragmentManager.beginTransaction();
ft.detach(fragment);
ft.attach(fragment);
ft.commit();
return rootView;
}
}
<RelativeLayout xmlns:ads="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<CheckBox
android:id="#+id/chkStarted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/start"
android:layout_below="#+id/chkInProgess"
android:gravity="top"
android:padding="4dp"
android:checked="true"
android:enabled="false"
android:layout_marginTop="10dp"
android:button="#xml/custom_checkbox_green"/>
<CheckBox
android:id="#+id/chkDownloaded"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_below="#+id/chkStarted"
android:text="#string/download"
android:gravity="top"
android:padding="4dp"
android:checked="true"
android:enabled="false"
android:button="#xml/custom_checkbox_green"/>
</RelativeLayout>
The textviews are not changing colors either at runtime, and I have tried to refresh the layouts, but they're not refreshing at runtime. They are what they need to be in the preview window, but they are not what they're supposed to be at runtime. Any help would be much appreciated. Thanks in advance!
I figured it out. I had read on some other stackoverflow pages that they set their textview to not visible and then visible. That didn't work for me, but I figured out that setting the checkboxes to unchecked and then checked again fixed it in the onCreateView.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_checklist, container, false);
chkStart = (CheckBox) rootView.findViewById(R.id.chkStarted);
chkDownload = (CheckBox) rootView.findViewById(R.id.chkDownloaded);
chkStart.setChecked(false);
chkStart.setChecked(true);
chkDownload.setChecked(false);
chkDownload.setChecked(true);
return rootView;
}
The problem was the checkboxes were already checked and that meant they were red and for it to appear green, it had to be unchecked then checked again. Also, I had other code that made it appear green. So, that was my solution.
Related
I am using fonttype defined this way, and android studio's layout design view is showing the string/textview in the weathericon font.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimaryLight">
<TextView
android:id="#+id/tvFragThird"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:fontFamily="#font/weathericons"
android:text="#string/textview"
android:textSize="30sp" />
</RelativeLayout>
But,when I am running this piece of code:
public class ThirdFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_third, container, false);
TextView tv = (TextView) v.findViewById(R.id.tvFragThird);
// Typeface typeface = ResourcesCompat.getFont(getContext(), R.font.weathericons);
// tv.setTypeface(typeface);
tv.setText("");//getArguments().getString("msg"));
return v;
}
I am just getting the text in normal font. I have tried both defining the fontfamily in layout and typeface in java, and none of them are working.
what I am missing?
As it's mentioned here https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml, custom font using fontFamily, needs API >= 26.
So change TextView tag to android.support.v7.widget.AppCompatTextView tag (if you use API < 26).
I had this problem and i came across above link and did above change and my problem is solved and i hope, it solves yours (if it has not been solved yet) and others.
Update:
As RobCo commented, if you can change to AppCompatActivity, you don't need above change. It's mentioned here : https://developer.android.com/reference/android/support/v7/widget/AppCompatTextView
I've been developing an app on Android 5.1.1, and everything works fine. But when I test it on a 4.0.4 device, none of the buttons display any text. Any idea why this would be?
Each button is the UI of a fragment. This is the layout, named just_a_button.xml:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/button_copper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#fff"
android:visibility="gone"/>
This is an example of how the fragments set up their views:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final Button button = (Button) inflater.inflate(R.layout.just_a_button, container, false);
button.setText(R.string.member_info);
// set click listener omitted
return button;
}
The button's visibility is controlled by an event receiver. The button is shown as expected, and its click listener works. There's just no text on it.
Edit: The solution was to put the button inside a layout. I'm still curious if this requirement was ever documented, and why only the text seems to be affected when the button is the root view.
Instead of this
button.setText(R.string.member_info);
use
button.setText(getActivity().getResources().getString(R.string.member_info));
You are directly defining string resource, but setText() takes string as parameter.
Edit:
change you xml like below and then findviewbyid for your button
<?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" >
<Button
android:id="#+id/Mybutton"
style="#style/button_copper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#fff"
android:visibility="gone"/>
</LinearLayout>
In your fragment onCreateView() do as below :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.just_a_button, container, false);
Button button = (Button) view.findViewById(R.id.Mybutton);
button.setText(getActivity().getResources().getString(R.string.member_info));
// set click listener omitted
return view;
}
I have a view pager consisting of 4 tabs. Each tab holds its own fragment.
How would I be able to use fragment transaction to replace the fragment in tab 3 with a new fragment?
I've tried a lot of things, but I have not been able to come up with a solution at all. I've tried looking around on google and stackoverflow, but with no success.
I assume that your fragment has a button that is put in the center. By clicking on it, you can change the layout stays under of this button. The content/layout of the first fragment you mentioned should be replaced with wrapperA and the content/layout of the second one should be replaced with wrapperB. I put a simple red background for wrapperA to distinguish it with wrapperB, wrapperB is also green due to the same reason. I hope this is what you want:
public class SwitchingFragment extends Fragment {
Button switchFragsButton;
RelativeLayout wrapperA, wrapperB;
View rootView;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.layout_switch, container, false);
wrapperA = (RelativeLayout) rootView.findViewById(R.id.wrapperA);
wrapperB = (RelativeLayout) rootView.findViewById(R.id.wrapperB);
switchFragsButton = (Button) rootView.findViewById(R.id.switchFragsButton);
switchFragsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (wrapperB.getVisibility() == View.GONE) {
wrapperB.setVisibility(View.VISIBLE);
// There is no need to change visibility of wrapperA since it stays behind when wrapperB is visible.
// wrapperA.setVisibility(View.GONE);
}
else {
wrapperB.setVisibility(View.GONE);
// Again, there is no need.
// wrapperA.setVisibility(View.VISIBLE);
}
}
});
return rootView;
}
}
The layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical">
<!-- The content of first fragment should be in "wrapperA". -->
<RelativeLayout
android:id="#+id/wrapperA"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/red"
android:visibility="visible">
</RelativeLayout>
<!-- The content of second fragment should be in "wrapperB". -->
<RelativeLayout
android:id="#+id/wrapperB"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/green"
android:visibility="gone">
</RelativeLayout>
<!-- As I said, I assume that the layout switcher button is stable
and so it should be in front of the switching layouts. -->
<Button
android:id="#+id/switchFragsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#color/black"
android:text="Switch"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#color/white"/>
</RelativeLayout>
Alternatively, you can try to change the fragment directly by notifying your FragmentPagerAdapter as described in this link:
Replace fragment with another fragment inside ViewPager
I've got a fragment which dynamially adds LinearLayouts with two imagebuttons and a edittext.
The Value from the edittext is stored in a .txt File and retrieved via the function retrievecounter.
This is the Layout which gets added:
<?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"
android:orientation="horizontal"
android:weightSum="100" >
<ImageButton
android:id="#+id/imageView1"
android:layout_width="56dp"
android:layout_height="50dp"
android:layout_weight="5"
android:src="#drawable/ic_action_photo" />
<EditText
android:id="#+id/singelfirstet1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="85"
android:ems="10" >
<requestFocus />
</EditText>
<ImageButton
android:id="#+id/buttonDelete"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="10"
android:background="#android:color/transparent"
android:contentDescription="#string/button_delete_row_description"
android:src="#drawable/testi" />
</LinearLayout>
This is my fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
ScrollView mLinearLayout = (ScrollView) inflater.inflate(
R.layout.editlistsfirst, container, false);
operations = new ArrayList<String>();
operations = retrievecounter(0);
temp = (LinearLayout) mLinearLayout.findViewById(R.id.lineartest);
LayoutInflater inflater2 = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (int i = 0; i < operations.size(); i++) {
View tempr = (inflater2.inflate(R.layout.list_singlefirst,
container, false));
ImageButton bt = (ImageButton) tempr
.findViewById(R.id.buttonDelete);
EditText et = (EditText) tempr.findViewById(R.id.singelfirstet1);
et.setText(operations.get(i));
String show = et.getText().toString();
Log.w("Class",show);
bt.setOnClickListener(this);
temp.addView(tempr);
}
return mLinearLayout;
}
I navigate between the fragments via an actionbar with tabs.
This is my onTabselected function:
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
ft.replace(R.id.fragment_container, fragment);
}
On the first click the values from the .txt file are displayed correctly, but after i switch to a different tab/fragment and back to this fragment only the last value of my ArrayList gets displayed.
Strange however is that the Log.w displays the correct value for the edittext both times.
Any idea what causes this?
Thanks in advance
If i call my function of the button inside the linearlayout:
temp.removeView((View) v.getParent());
for all buttons till all layouts are gone and go to another tab and back it displays the correct values, but i've got no idea why. Maybe this is helpful in finding the problem.
edit2: I Found a solution, don't know if it is practical or why it works but it does:
public void onPause(){
super.onPause();
temp.removeAllViews();
}
After i added this it works. If someone could explain why that would be much appreciated.
One of the things to consider when dealing with Views like this is that they are only 'updated' when they are first created. When you switch between your tabs, the data will not be refreshed because it was A)Not recreated [refreshed] B)Not updated by an adapter.
When you removed all views on Pause(), you emptied your view, then it is recreated from your replace() function which is similar as creating a new view. Refreshing a layout by removing and re-adding everything every time you change something can become very computationally expensive which is why people will use an adapter to control their layouts.
How can I add a simple static header to my listview inside a listFragment? I want to create the header from an xml def and add it through inflation.
My onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View detailList = inflater.inflate(R.layout.detail_fragment, container, false);
View detailListHeader = inflater.inflate(R.layout.daily_sales_header, null, false);
container.addView(detailListHeader, 0);
return detailList;
}
This creates the header, but it is not above the listview, rather the listview appears underneath the header, ie the header is overlaying the listview.
Any hints on the correct implementation?
Putting hackbod's description into code for you since his answer created more questions before the answers came. Sometimes I just want the fish. I don't always need to know how the net is made...
To start with, create a layout that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myListViewWithHeader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp"
android:textStyle="bold"
android:textSize="20sp" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false" />
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Then, in your onCreateView method you do this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.myListViewWithHeader, null);
return view;
}
The header can now be populated by doing this:
// get the header view
TextView headerView = (TextView) getView().findViewById(R.id.header);
headerView.setText("Header text goes here");
Notice that my header is a TextView, but it can be replaced with another view if you like. In that case you will need to do a getView().findViewById(R.id.xxxxx) for each view inside the header you want to work with
You should NEVER EVER be adding views directly to the container in onCreateView(). Please read the documentation: http://developer.android.com/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
Also see the various sample code in the Fragment documentation, as well as the API demos: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/index.html
There is nothing special about using a Fragment here. Just build a view hierarchy containing a ListView like you normally would in an Activity or elsewhere. You always need to return one View from onCreateView; this is the root of your hierarchy.
For example you could make the ListView and then use this to add a header to it: http://developer.android.com/reference/android/widget/ListView.html#addHeaderView(android.view.View)