I have an app that I desperately need to convert from using the old ActivityGroup class to Fragments. I'm not sure how to go about it though. Below is a sample of the code I use now. Could anyone provide some insight into what steps I should take to start switching it over to use Fragments / FragmentManager instead?
Main.java
public class Main extends TabActivity implements OnTabChangeListener {
public static TextView txtViewHeading;
public static Button btnBack;
public static ImageButton btnShare;
public static Main mainActivity;
public static Boolean isVisible = false;
private GoogleCloudMessaging gcm;
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mainActivity = this;
NotificationsManager.handleNotifications(this, NotificationSettings.SenderId, PushHandler.class);
registerWithNotificationHubs();
//reference headings text & button for access from child activities
txtViewHeading = (TextView) findViewById(R.id.txtViewHeading);
btnBack = (Button) findViewById(R.id.btnBack);
btnShare = (ImageButton) findViewById(R.id.btnShare);
// Update the font for the heading and back button
Typeface arialTypeface = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/arial.ttf");
Typeface myriadTypeface = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/myriad.ttf");
txtViewHeading.setTypeface(myriadTypeface);
btnBack.setTypeface(arialTypeface);
Resources res = getResources();
TabHost tabsNavigation = getTabHost();
// Set up the views for each tab - custom view used for Badge icon
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Set up my tabs...each one looks similar to this
View statusTabView = inflater.inflate(R.layout.tab, null);
ImageView statusTabIcon = (ImageView) statusTabView.findViewById(R.id.tabIcon);
statusTabIcon.setImageResource(R.drawable.tab_first);
TextView statusTabText = (TextView) statusTabView.findViewById(R.id.tabText);
statusTabText.setText("Status");
statusTabText.setTypeface(arialTypeface);
statusTabBadge = (TextView) statusTabView.findViewById(R.id.tabBadge);
statusTabBadge.setTypeface(arialTypeface);
tabsNavigation.addTab(tabsNavigation.newTabSpec(getResources().getString(R.string.main_tab_status))
.setIndicator(statusTabView)
.setContent(new Intent(this, StatusGroupActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)));
//Set default tab to Status
tabsNavigation.setCurrentTab(0);
tabsNavigation.setOnTabChangedListener(this);
}
/* Set txtViewHeading text to selected tab text */
#Override
public void onTabChanged(String tabId) {
// TODO Auto-generated method stub
txtViewHeading.setText(tabId);
}
/* Set code to execute when onDestroy method is called */
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
/* Set code to execute when onPause method is called */
#Override
protected void onPause() {
super.onPause();
isVisible = false;
}
/* Set code to execute when onResume method is called */
#Override
protected void onResume() {
super.onResume();
isVisible = true;
}
/* Set code to execute when onStop method is called */
#Override
protected void onStop() {
super.onStop();
isVisible = false;
}
/**
* Check the device to make sure it has the Google Play Services APK. If
* it doesn't, display a dialog that allows users to download the APK from
* the Google Play Store or enable it in the device's system settings.
*/
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
ToastNotify("This device is not supported by Google Play Services.");
finish();
}
return false;
}
return true;
}
public void ToastNotify(final String notificationMessage) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(Main.this, notificationMessage, Toast.LENGTH_LONG).show();
}
});
}
public void registerWithNotificationHubs()
{
if (checkPlayServices()) {
// Start IntentService to register this application with GCM.
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
}
}
TabGroupActivity.java
public class TabGroupActivity extends ActivityGroup
{
private ArrayList<String> mIdList;
Button btnBack;
ImageButton btnShare;
TextView txtViewHeading;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
btnBack = Main.btnBack;
btnShare = Main.btnShare;
txtViewHeading = Main.txtViewHeading;
btnBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
if (mIdList == null) mIdList = new ArrayList<String>();
}
/**
* This is called when a child activity of this one calls its finish method.
* This implementation calls {#link LocalActivityManager#destroyActivity} on the child activity
* and starts the previous activity.
* If the last child activity just called finish(),this activity (the parent),
* calls finish to finish the entire group.
*/
#Override
public void finishFromChild(Activity child)
{
try
{
btnShare.setVisibility(View.GONE);
LocalActivityManager manager = getLocalActivityManager();
int index = mIdList.size()-1;
if (index < 1)
{
finish();
return;
}
manager.destroyActivity(mIdList.get(index), true);
mIdList.remove(index);
index--;
String lastId = mIdList.get(index);
Intent lastIntent = manager.getActivity(lastId).getIntent();
Window newWindow = manager.startActivity(lastId, lastIntent);
setContentView(newWindow.getDecorView());
//Set Heading text to current Id
txtViewHeading.setText(getActivityHeading(lastId));
//Set Back button text to previous Id if applicable
btnBack.setVisibility(View.VISIBLE);
//Back button
String backId = "";
if(mIdList.size() > 1)
{
backId = mIdList.get(mIdList.size()-2);
btnBack.setVisibility(View.VISIBLE);
btnBack.setText(getActivityHeading(backId));
txtViewHeading.setPadding(10,0,0,0);
}
else
{
btnBack.setVisibility(View.GONE);
txtViewHeading.setPadding(0,0,0,0);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* Starts an Activity as a child Activity to this.
* #param Id Unique identifier of the activity to be started.
* #param intent The Intent describing the activity to be started.
*/
public void startChildActivity(String Id, Intent intent)
{
try
{
btnShare.setVisibility(View.GONE);
Window window = getLocalActivityManager().startActivity(Id,intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
if (window != null)
{
mIdList.add(Id);
setContentView(window.getDecorView());
txtViewHeading.setText(getActivityHeading(Id));
//Back button
String backId = "";
if(mIdList.size() > 1)
{
backId = mIdList.get(mIdList.size()-2);
btnBack.setVisibility(View.VISIBLE);
btnBack.setText(backId);
txtViewHeading.setPadding(5,0,0,0);
}
else
{
btnBack.setVisibility(View.GONE);
txtViewHeading.setPadding(0,0,0,0);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* The primary purpose is to prevent systems before android.os.Build.VERSION_CODES.ECLAIR
* from calling their default KeyEvent.KEYCODE_BACK during onKeyDown.
*/
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
//preventing default
return true;
}
return super.onKeyDown(keyCode, event);
}
/**
* Overrides the default implementation for KeyEvent.KEYCODE_BACK
* so that all systems call onBackPressed().
*/
#Override
public boolean onKeyUp(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
onBackPressed();
return true;
}
return super.onKeyUp(keyCode, event);
}
/**
* If a Child Activity handles KeyEvent.KEYCODE_BACK.
* Simply override and add this method.
*/
#Override
public void onBackPressed ()
{
try
{
btnShare.setVisibility(View.GONE);
int length = mIdList.size();
if ( length > 1)
{
Activity current = getLocalActivityManager().getActivity(mIdList.get(length-1));
current.finish();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* Get the correct heading text and language based on activity id
*/
public String getActivityHeading(String id)
{
// method that returns the TEXT for my main heading TextView based on the activity we're on...
}
}
StatusGroupActivity
public class StatusGroupActivity extends TabGroupActivity
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startChildActivity("Status", new Intent(this,Status.class));
}
}
... so basically when my app loads, I get my tabs at the bottom, my header at the top, and the "tab content" in the middle. In my Status activity, I can load another activity from it by using ...
Intent intent = new Intent(getParent(), SomeOtherActivity.class)
TabGroupActivity parentActivity = (TabGroupActivity)getParent();
parentActivity.startChildActivity("Some Other Activity", intent);
... and it loads the SomeOtherActivity activity into the content area. Hitting back takes me back to the Status screen.
Any pointers, examples and assistance with converting this over to use Fragments is so greatly appreciated. I will gladly donate 500 of my rep. points for a full example.
main.xml (Main Activity Layout file)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
tools:ignore="ContentDescription,HardcodedText" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/imageSuccess"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:scaleType="matrix"
android:src="#drawable/bg_navbar_blank" />
<com.myproject.android.BgButtonStyle
android:id="#+id/btnBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="0dp"
android:background="#drawable/back_button"
android:text=""
android:textColor="#color/White"
android:textSize="12sp"
android:visibility="visible"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:padding="5dp"/>
<ImageButton
android:id="#+id/btnShare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:background="#null"
android:src="#drawable/icon_share"
android:visibility="visible"
android:adjustViewBounds="false"
android:scaleType="fitXY"/>
<com.myproject.android.AutoResizeTextView
android:id="#+id/txtViewHeading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingLeft="5dp"
android:text="Status"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="28sp"
android:textStyle="bold"
android:paddingRight="5dp"
android:layout_toEndOf="#id/btnBack"
android:layout_toStartOf="#id/btnShare"
android:layout_centerVertical="true"
android:lines="1"/>
</RelativeLayout>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
</FrameLayout>
<TabWidget
android:id="#android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-4dp"
android:layout_weight="0"
android:background="#drawable/bg_tabs">
</TabWidget>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
In my current TabGroupActivity class, in the finishFromChild and startChildActivity methods, I am able to call setText on the txtViewHeading TextView element in my main activity layout. Which is the current activities "title". If there is more than 1 activity in the group, the back button shows the previous title. How can I duplicate this in the examples below? The main activity layout there is much different than mine.
First you need to add Design Support Library and AppCompatLibrary into your Project
Add this code into your app gradle
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support:design:24.0.0'
layout for activity_main.xml (like main.xml in your code)
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
In above layout ViewPager will provides horizontal layout to display tabs. You can display more screens in a single screen using tabs. You can swipe the tabs quickly as you can.
Root Fragment
<FrameLayout 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"
android:id="#+id/root_frame" >
View for First Fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#ff0"
android:layout_height="match_parent" >
<TextView
android:id="#+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:text="#string/first_fragment" />
<Button
android:id="#+id/btn"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:text="#string/to_second_fragment"/>
</RelativeLayout>
View for Second and Individual(s) Fragment.
<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"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin">
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
Now add a MainActivity(like Main Activity in yours code) under which all this thing will handle.
public class MainActivity extends AppCompatActivity {
private TabGroupAdapter mTabGroupAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ArrayList<Fragment> fragmentList = new ArrayList<Fragment>();
fragmentList.add(new RootFragment());
fragmentList.add(new IndividualFragment1());
fragmentList.add(new IndividualFragment2());
ArrayList<String> name = new ArrayList<String>() {
{
add("Root Tab");
add("Second Tab");
add("Third Tab");
}
};
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mTabGroupAdapter = new TabGroupAdapter(getSupportFragmentManager(),name, fragmentList,);
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mTabGroupAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
}
There is one FragmentPagerAdapter defined as mTabGroupAdapter inside MainActivity that will add a different tabs inside a single Layout.
First we bind the mTabGroupAdapter to mViewPager.
TabLayout will act like a TabHost under which Tab will be added by FragmentPagerAdapter.
mViewPager is bind to the Tablayout.
Under MainActivity TabLayout will display the name of Tabs.
TabGroupAdapter
public class TabGroupAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragmentList = new ArrayList<Fragment>();
private ArrayList<String> fragment_name;
public TabGroupAdapter(FragmentManager fm, ArrayList<String> name, ArrayList<Fragment> list) {
super(fm);
this.fragmentList = list;
this.fragment_name = name;
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return fragment_name.get(position);
}
}
In TabGroupAdapter you would pass a List of fragments(or single fragment) and list of fragments name(or single name) as arguments in the Constructor.
IndividualFragment(s) will act like a individual Tab instead of Activity.
RootFragment will be acting as a container for other fragments( First Fragment and Second Fragment)
Root Fragment
public class RootFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.root_fragment, container, false);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.root_frame, new FirstFragment());
fragmentTransaction.commit();
return view;
}
}
First Fragment
public class FirstFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.first_fragment, container, false);
Button btn = (Button) view.findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
//use the "root frame" defined in
//"root_fragment.xml" as the reference to replace fragment
fragmentTransaction.replace(R.id.root_frame, new SecondFragment());
/*
* allow to add the fragment
* to the stack and return to it later, by pressing back
*/
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
}
}
Second Fragment
public class SecondFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
Individual(s) Fragment
public class IndividualFragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
public class IndividualFragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
In OnCreateView method you would set a layout of a Tab .
You won't have to use the getTabHost() method.
Let me know if you persist any problem.
Whenever you want to dynamically change or update the Tabs in View Pager just add or remove item from fragmentList and call this method mTabGroupAdapter.notifyDataSetChanged(); inside MainActivity.
Add these dependencies to your project:
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
First change your Main activity must be extended from AppCompatActivity.
Than change your main activity's layout like below:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/coordinatorlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".Main">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<include
layout="#layout/toolbar_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:tabGravity="fill"
app:tabMaxWidth="0dp"
app:tabIndicatorHeight="4dp"
app:tabMode="fixed"
app:tabIndicatorColor="#android:color/white"
android:background="#color/AppPrimary"/>
</android.support.design.widget.AppBarLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".dashboard.DashboardActivity"
tools:showIn="#layout/activity_dashboard">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
And here's a toolbar layout example. You can customize however you want.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar_main"
style="#style/Widget.MyApp.Toolbar.Solid"
android:layout_width="match_parent"
android:layout_height="#dimen/abc_action_bar_default_height_material"
android:background="#color/AppPrimary"
app:contentInsetEnd="16dp"
app:contentInsetStart="16dp" />
Than you need to create fragments which you'll use in your tabs instead of activities which you use for tabs. In this case this'll your Status Activity if i'm not wrong.
Define a StatusFragment like below:
public class StatusFragment extends Fragment
{
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// this is your Status fragment. You can do stuff which you did in Status activity
}
}
Than you need to define a tabs adapter which you'll bind with your tabs and convert your TabHost to Fragment/Fragment manager type. Titles string array contains strings which you'll show in your tabs indicator. Such as "Status, My Assume Tab, My awesome tab 2
public class DashboardTabsAdapter extends FragmentPagerAdapter {
private String[] mTitles;
public DashboardTabsAdapter(FragmentManager fm, String[] titles) {
super(fm);
this.mTitles = titles;
}
#Override
public Fragment getItem(int position) {
return new StatusFragment();
// You can define some other fragments if you want to do different types of operations in your tabs and switch this position and return that kind of fragment.
}
#Override
public int getCount() {
return mTitles.length;
}
#Override
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
}
And finally in your Main activity find your view pager, tabs create a new adapter and bind them.
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
final DashboardTabsAdapter dashboardTabsAdapter = new DashboardTabsAdapter(getSupportFragmentManager(), getResources().getStringArray(R.array.tab_titles));
mViewPagerMain = (ViewPager) findViewById(R.id.viewpager_main);
mViewPagerMain.setOffscreenPageLimit(3);
mViewPagerMain.setAdapter(dashboardTabsAdapter);
tabLayout.setupWithViewPager(mViewPagerMain);
Edit: You'll no longer need TabHost and TabActivity any more. Your tab grup activity will be your ViewPager which handles screen changes and lifecycle of fragments inside. If you need to get this activity from fragments you can use getActivity() method and cast it to your activity and use it's public methods.
Related
I am building a quiz app with three questions and therefore I have 6 Fragments but I would like to disable the default transition from one fragment to another, how can I achieve this? I already disabled that you can swipe between the fragments, you have to click a button to get to the next fragment, but there is still somehow a swiping transition after clicking the button. I searched for this but there was never an answer that would fit my problem. Here is one fragment example:
public class FragmentQuestion1 extends Fragment {
private Button btnNavFrag1;
private EditText editText;
private ProgressBar m_bar;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_question_1, container, false);
btnNavFrag1 = view.findViewById(R.id.btn_question1);
editText = view.findViewById(R.id.edit_text_question_1);
editText.addTextChangedListener(new NumberTextWatcher(editText));
m_bar = view.findViewById(R.id.progress_bar_question_1);
btnNavFrag1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((GameActivity)getActivity()).setViewPager(2);
}
});
return view;
}
// Method that is used so the countdown starts when the user gets to this fragment
#Override
public void setMenuVisibility(final boolean visible) {
super.setMenuVisibility(visible);
if (visible) {
startCountdownTimer();
}
}
// Countdown 17 seconds
int i = 0;
private void startCountdownTimer() {
m_bar.setProgress(i);
final int totalMsecs = 17 * 1000; // 17 seconds in milli seconds
int callInterval = 100;
/** CountDownTimer */
new CountDownTimer(totalMsecs, callInterval) {
public void onTick(long millisUntilFinished) {
int secondsRemaining = (int) millisUntilFinished / 1000;
float fraction = millisUntilFinished / (float) totalMsecs;
// progress bar is based on scale of 1 to 100;
m_bar.setProgress((int) (fraction * 100));
}
public void onFinish() {
}
}.start();
}
Because you are using a viewPager, you could use a library like this which lets you add a transformer (some sort of effect) to the viewPager when going to the next fragment. I'd recommend the ZoomOutTranformer for your use-case. If the transition is not what you expect you can always extend from that class and override the transition so it's more to your liking.
ViewPagerTransformers are native, so you don't need to use a library. Just create a class, implement the PageTransformer interface and override the method transformPage.
In your layout xml define a tablayout and a FrameLayout like this:
..................your xml code...............
.............................................................
<com.google.android.material.tabs.TabLayout
android:id="#+id/simpleTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#color/colorPrimary"
app:tabIndicatorColor="#0080FF"
app:tabSelectedTextColor="#050505"
app:tabTextColor="#color/colorAccent">
<com.google.android.material.tabs.TabItem
android:id="#+id/abcd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item 1" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="item 2" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="item 3" />
</com.google.android.material.tabs.TabLayout>
<FrameLayout
android:id="#+id/simpleFrameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
This layout is defined for three tabs. You can make it for more tabs by adding more tabs if you like.
Then define the fragments for each tab. In this case:
item_one_fragment:
<?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="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="your.activity.context">
......................................
............................................
fragments xml
.............................
,.....................................
</RelativeLayout>
Similarly item 2 and item 3 fragment layouts.
Then define the fragments in java:
public class FirstItemFragment extends Fragment {
public ListView CallListView;
public FirstFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.item_one_fragment, container, false);
// Inflate the layout for this fragment
return view;
}
}
Simiarly second and third fragment.
Then in your Main Activity:
FrameLayout simpleFrameLayout = (FrameLayout) findViewById(R.id.simpleFrameLayout);
TabLayout tabLayout = (TabLayout) findViewById(R.id.simpleTabLayout);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.simpleFrameLayout, new FirstItemFragment());
ft.commit();
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
// get the current selected tab's position and replace the fragment accordingly
Fragment fragment = null;
switch (tab.getPosition()) {
case 0:
fragment = new FirstItemFragment();
break;
case 1:
fragment = new SecondItemFragment();
break;
case 2:
fragment = new ThirdItemFragment();
break;
}
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.simpleFrameLayout, fragment)
.addToBackStack(null)
//Commit the transaction.
.commit();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
Now when you run your activity you will have three tabs and when you click on any one you will go to the respective fragment without any swipe
Okay. I am stuck and having a headache... I am not sure how to access the other layout's view, since inflating does not work.
Here are my codes.
WriteRouteActivity.java
public class WriteRouteActivity extends AppCompatActivity {
private Toolbar tb;
private TextView txt_toolbar_title;
private Button btnSearchPlaces;
private LinearLayout parentLayout, placesCoverLayout;
private View popupView;
private ImageView imgShowPlaces;
private boolean isKeyBoardVisible;
private int keyboardHeight;
private EditText edtSearchPlaces;
private PopupWindow popupWindow;
//popupView
private TabLayout tabLayout;
private FrameLayout frameLayout;
//prework
private int minusVal;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_route);
initView();
}
private void initView() {
//for activity and native back button
tb = (Toolbar) findViewById(R.id.nav_toolbar);
setSupportActionBar(tb);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
txt_toolbar_title = (TextView) findViewById(R.id.txt_toolbar);
parentLayout = (LinearLayout) findViewById(R.id.layout_parent);
placesCoverLayout = (LinearLayout) findViewById(R.id.footer_for_places);
imgShowPlaces = (ImageView) findViewById(R.id.img_show_places);
edtSearchPlaces =(EditText) findViewById(R.id.edt_search_place);
btnSearchPlaces = (Button) findViewById(R.id.btn_search_place);
popupView = getLayoutInflater().inflate(R.layout.places_popup, null);
tabLayout = (TabLayout) popupView.findViewById(R.id.tab_layout);
frameLayout = (FrameLayout) popupView.findViewById(R.id.frame_layout);
doWorkForLayotus();
}
private void doWorkForLayotus(){
final float popUpheight = getResources().getDimension(R.dimen.keyboard_height);
changeKeyboardHeight((int) popUpheight);
enablePopUpView();
setTabLayout();
checkKeyboardHeight(parentLayout);
enableFooterView();
}
public void setCurrentTabFragment(int position) throws IllegalAccessException, InstantiationException {
String tag="";
Fragment fr = null;
Class frClass = null;
FragmentManager frManager = getSupportFragmentManager();
switch (position) {
case 0:
tag = "first";
//hide
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("second")).commit();
}
if(frManager.findFragmentByTag("third")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("third")).commit();
}
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("fourth")).commit();
}
//show
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("first")).commit();
}else{ //add
try {
frManager.beginTransaction().add(frameLayout.getId(), ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}catch(Exception e){
Log.e("why", e.getMessage().toString());
}
}
break;
case 1:
tag = "second";
//hide
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("first")).commit();
}
if(frManager.findFragmentByTag("third")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("third")).commit();
}
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("fourth")).commit();
}
//show
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("second")).commit();
}else{ //add
frManager.beginTransaction().add(frameLayout.getId(), ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}
break;
case 2:
tag = "third";
//hide
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("first")).commit();
}
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("second")).commit();
}
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("fourth")).commit();
}
//show
if(frManager.findFragmentByTag("third")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("third")).commit();
}else{ //add
frManager.beginTransaction().add(frameLayout.getId(), ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}
break;
case 3:
tag = "fourth";
//hide
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("first")).commit();
}
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("second")).commit();
}
if(frManager.findFramentByTag("third")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("third")).commit();
}
//show
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("fourth")).commit();
}else{ //add
frManager.beginTransaction().add(R.id.frame_layout, ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}
break;
}
//frManager.beginTransaction().replace(R.id.frame_container, fr, tag).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit();
}
private void setTabLayout(){
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
try {
setCurrentTabFragment(tab.getPosition());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void enablePopUpView() {
// Creating a pop window for emoticons keyboard
popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT,
(int) keyboardHeight, false);
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
placesCoverLayout.setVisibility(LinearLayout.GONE);
}
});
}
int previousHeightDiffrence = 0;
private void checkKeyboardHeight(final View parentLayout) {
parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
parentLayout.getWindowVisibleDisplayFrame(r);
int screenHeight = parentLayout.getRootView()
.getHeight();
minusVal=screenHeight-r.bottom;
int heightDifference = screenHeight - (r.bottom+(minusVal));
if (previousHeightDiffrence - heightDifference > 50) {
popupWindow.dismiss();
}
previousHeightDiffrence = heightDifference;
if (heightDifference > 100) {
isKeyBoardVisible = true;
changeKeyboardHeight(heightDifference);
} else {
isKeyBoardVisible = false;
}
}
});
}
private void changeKeyboardHeight(int height) {
if (height > 100) {
keyboardHeight = height;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, keyboardHeight);
placesCoverLayout.setLayoutParams(params);
}
}
private void enableFooterView() {
edtSearchPlaces.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (popupWindow.isShowing()) {
popupWindow.dismiss();
}
}
});
btnSearchPlaces.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
hideSoftKeyboard(WriteRouteActivity.this);
if(!popupWindow.isShowing()){
popupWindow.setHeight((int) (keyboardHeight));
if (isKeyBoardVisible) {
placesCoverLayout.setVisibility(LinearLayout.GONE);
} else {
placesCoverLayout.setVisibility(LinearLayout.VISIBLE);
}
popupWindow.setSoftInputMode(PopupWindow.INPUT_METHOD_NEEDED);
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
popupWindow.showAtLocation(parentLayout, Gravity.BOTTOM, 0, 0);
try {
setCurrentTabFragment(0);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
} else {
//popupWindow.dismiss();
}
}
});
}
#Override
protected void onDestroy() {
popupWindow.dismiss();
super.onDestroy();
}
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
#Override
public void onBackPressed() {
if(popupWindow.isShowing()){
popupWindow.dismiss();
}else {
super.onBackPressed();
}
}
}
activity_write_wroute.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/nav_toolbar" />
<fragment
android:id="#+id/google_map"
class="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<include
android:id="#+id/footer_layout"
layout="#layout/footer_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/footer_for_places"
android:layout_width="match_parent"
android:layout_height="#dimen/keyboard_height"
android:background="#android:color/transparent"
android:orientation="vertical"
android:visibility="gone" />
</LinearLayout>
Fragment_Zasin
public class Fragment_zasin extends Fragment {
public Fragment_zasin newInstance() {
Fragment_zasin fr = new Fragment_zasin();
return fr;
}
public Fragment_zasin() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_zasin, container, false);
return rootView;
}
}
places_popup.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/linear_layout_top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="fill_parent"
android:layout_height="?attr/actionBarSize"
android:background="#ffffff"
app:tabGravity="fill"
app:tabIndicatorColor="#color/colorPrimary"
app:tabIndicatorHeight="4dp"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/colorPrimary">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_pin_selector"
android:text="11">
</android.support.design.widget.TabItem>
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_mainroute_selector"
android:text="22" />
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_talk_selector"
android:text="33" />
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_my_selector"
android:text="44" />
</android.support.design.widget.TabLayout>
<FrameLayout
android:id="#+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
</LinearLayout>
LOGCAT Message
FATAL EXCEPTION: main Process: suacuration.itgotravel, PID: 20131
java.lang.IllegalArgumentException: No view found for id 0x7f100173 for fragment Fragment_zasin{d4ac39c #0 id=0x7f100173 first}
Can somebody help this?
This error occurs because the fragment manager could not find the view on which it has to inflate the fragment.
The fragment transaction is linked to the activity so this error occurs as the frame layout is not a part of that main activity's xml.so it cant find where to add the fragment.fragment has to be added inside the activity.
what you have to do is provide the id of a view in your main activity.
for e.g your main view
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mainView"//like this
android:orientation="vertical">
<include layout="#layout/nav_toolbar" />
<fragment
android:id="#+id/google_map"
class="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<include
android:id="#+id/footer_layout"
layout="#layout/footer_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/footer_for_places"
android:layout_width="match_parent"
android:layout_height="#dimen/keyboard_height"
android:background="#android:color/transparent"
android:orientation="vertical"
android:visibility="gone" />
</LinearLayout>
The view where you are trying to inflate the fragemnt must be inside activity.
Now when you try
frManager.beginTransaction().add(R.id.mainView, ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
the fragment will be loaded on this view of your activity.
Problem is you are trying to show a Fragment on a View which is not defined in your layout which you have defined in your onCreate() while setContentView(layoutId)
In your case you are inflating fragments in WriteRouteActivity where layout defined is activity_write_route and fragments are added on FrameLayout which is defined in places_popup.xml so define your framelayout in a view layout of Activity.
Small Description :
--------code------
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-------layout define for activity-------
setContentView(R.layout.activity_write_route);
}
now where you are adding fragment on a FrameLayout(view)
frManager.beginTransaction().add(R.id.frame_layout, ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
here R.id.frame_layout should be define in your layout activity_write_route.
Okay i found an answer.
The problem was that fragment cannot be a child of a 'Dialog'.
Since i used popup dialog, it was unable to put fragments inside the dialog.
i solved by inflating views rather than using fragments in tablayout.
There could be other errors but what is this?
tb = (Toolbar) findViewById(R.id.nav_toolbar);
This is not a toolbar:
<include layout="#layout/nav_toolbar" />
Can we see inside this nav_toolbar layout?
Also, where is this: "R.layout.fragment_zasin". It's complaining about a Fragment so it would be worthwhile seeing if this is ok.
Anyway, as a general troubleshooting strategy, try commenting out all those lines in the initView() method and just add them in one at a time until it fails. Or maybe if you scroll down in the error logs further it will give you a hyperlink to the line that's causing it to fail.
Why do you have "frameLayout.getId()" on one line but "R.id.frame_layout" on another? Try to use the latter for all of the lines and see if that's it.
I was extending the wrong type of activity, extended AppCompact solved issue.
Got this error when starting new fragment from fragment, using ChildFragmentManager, and giving id of container from activity, in transaction replace method.
It happens that FragmentManager has access to activity containers, but ChildFragmentManager has access to fragment containers.
The solution was to use FragmentManager class instead of ChildFragmentManager.
You got this error because your view found for id 0x7f100173 into fragment Fragment_zasin so only solution is that:
1) check all id present to that particular layout.
2) if all id is present to that particular layout and still you facing same issue do one thing change name of id don't refactor change name and access this changed id name in your fragment or activity.
I am using fragments,I have an edittext in fragment and I want to get value in main activity.
This is my fragment 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:orientation="vertical"
android:background="#878787" >
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="dfgdfgdf"
android:textSize="20dp"
android:layout_centerInParent="true"
android:id="#+id/user_name"/>
<EditText
android:id="#+id/message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:text="Gönder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="getFromUser"
android:layout_marginTop="40dp"
/>
</RelativeLayout>
I am loading fragment with this function:
public void startChat(JsonObject user) {
FrameLayout layout = (FrameLayout)findViewById(R.id.container);
layout.setVisibility(View.VISIBLE);
Bundle bundle = new Bundle();
bundle.putString("name", user.get("name").getAsString());
sendTo=user.get("username").getAsString();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ConversationFragment conv = new ConversationFragment();
conv.setArguments(bundle);
fragmentTransaction.add(R.id.container, conv);
fragmentTransaction.commit();
viewPager.setVisibility(View.GONE);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayHomeAsUpEnabled(true);
}
And this is my fragment class
public class ConversationFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String name = getArguments().getString("name");
View rootView = inflater.inflate(R.layout.fragment_conversation, container, false);
TextView username=(TextView)rootView.findViewById(R.id.user_name);
username.setText(name);
return rootView;
}
}
As you can see when press the button main activity runs "getFromUser" function.I want to get edittext value in this function.How can I do this ?
It's always the same procedure for these things. You can't access a fragment's views just like that. You need a callback method.
Add this code to ConversationFragment:
private OnGetFromUserClickListener mListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnGetFromUserClickListener ) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnGetFromUserClickListener");
}
}
public void getFromUser(View v) {
if (mListener != null) {
EditText edit = (EditText)findViewById(R.id.message);
mListener.getFromUser(edit.getText().toString());
}
}
public interface OnGetFromUserClickListener {
void getFromUser(String message);
}
Make your MainActivity implement this interface. Replace getFromUser() inside MainActivity with:
public void getFromUser(String message) {
sendMessage(message);
}
Done.
Edit:
Actually, using the XML-onClick attribute is currently bugged (see onClick inside fragment called on Activity): It links to the activity instead of the fragment. You have to set the click listener programmatically to make sure the code won't break at some point in the future. So give the button an ID inside the XML (e.g. get_from_user) and add this code to onCreateView inside ConversationFragment:
v.findViewById(R.id.get_from_user).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (v.getId() == R.id.get_from_user) {
getFromUser(v);
}
}
});
Using this code vastly decouples the activity and the fragment from each other.
I resolved this problem.
public void getFromUser(View view) {
ConversationFragment fragment1 = (ConversationFragment)getSupportFragmentManager().findFragmentById(R.id.container);
View frag=fragment1.getView();
EditText editText1 =(EditText) frag.findViewById(R.id.message);
String message=editText1.getText().toString();
sendMessage(message);
}
Now I can get edittext value from fragment.
So I want to have 3 buttons that always appear throughout fragments. I've got an activity with 3 buttons and a fragment layout that contains a fragment with actionbarsherlock inside. The problem is, the buttons in the activity are not clickable and nothing can be executed in the OnClickListener; but the buttons run just fine if I replace the fragment containing actionbarsherlock with a regular fragment without actionbarsherlock inside. I wonder what's wrong.
Here is my code.
activity_main.xml:
<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"
android:paddingBottom="2dp"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<FrameLayout
android:id="#+id/fragment_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/button1" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/fragment_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:text="mission" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button1"
android:layout_alignBottom="#+id/button1"
android:layout_centerHorizontal="true"
android:text="feed" />
<Button
android:id="#+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button2"
android:layout_alignBottom="#+id/button2"
android:layout_alignRight="#+id/fragment_content"
android:text="Profile" />
</RelativeLayout>
MyActivity.java:
public class MyActivity extends SherlockFragmentActivity {
/**
* Called when the activity is first created.
*/
Fragment frg;
ActionBarFragment b;
Button btnmission;
Button btnfeed;
Button btnprofile;
boolean small;
static int previousItem;
int tabname;
private Fragment mVisible = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
previousItem=1;
btnmission = (Button) findViewById(R.id.button1);
btnfeed = (Button) findViewById(R.id.button2);
btnprofile = (Button) findViewById(R.id.button3);
btnmission.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i("clicked", "button");
if(previousItem!=1){
Intent intent=new Intent(getBaseContext(),MyActivity.class);
startActivity(intent);
}
previousItem=1;
}
});
btnfeed.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(previousItem!=2){
Intent intent=new Intent(getBaseContext(),MissionFragment.class);
intent.putExtra("class", "Feed");
startActivity(intent);
}
previousItem=2;
}
});
btnprofile.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
private void setupFragments() {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
frg = (ActionBarFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_content);
if (frg == null) {
frg = new ActionBarFragment();
ft.add(R.id.fragment_content, frg);
}
ft.hide(frg);
ft.commit();
}
private void showFragment(Fragment fragmentIn) {
if (fragmentIn == null) return;
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
if (mVisible != null) ft.hide(mVisible);
ft.show(fragmentIn).commit();
mVisible = fragmentIn;
}
It adds a fragment to the activity and actionbar inside the fragment.
ActionBarFragment.java:
public class ActionBarFragment extends SherlockFragment {
int tabname;
#Override
public void onStart()
{
// TODO Auto-generated method stub
super.onStart();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.empty_view, container, false);
// Getting an instance of action bar
ActionBar actionBar = this.getSherlockActivity().getSupportActionBar();
// Enabling Tab Navigation mode for this action bar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Enabling Title
actionBar.setDisplayShowTitleEnabled(true);
// Creating Android Tab
Tab tab1 = actionBar.newTab()
.setText("Nova Missoes")
.setTabListener(new CustomTabListener<ListMission>(this.getSherlockActivity(), "mission list", ListMission.class));
// Adding Android Tab to action bar
actionBar.addTab(tab1);
// Creating Apple Tab
Tab tab2 = actionBar.newTab()
.setText("Missoes Concluidas")
.setTabListener(new CustomTabListener<MissionAccomplished>(this.getSherlockActivity(), "mission accomplished", MissionAccomplished.class));
// Adding Apple Tab to action bar
actionBar.addTab(tab2);
Intent in=getSherlockActivity().getIntent();
tabname=in.getIntExtra("tabname", 0);
Log.i("intent", Integer.toString(tabname));
if(tabname==2){
actionBar.selectTab(tab2);
}
// Orientation Change Occurred
if(savedInstanceState!=null){
int currentTabIndex = savedInstanceState.getInt("tab_index");
actionBar.setSelectedNavigationItem(currentTabIndex);
}
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
int currentTabIndex = getSherlockActivity().getSupportActionBar().getSelectedNavigationIndex();
outState.putInt("tab_index", currentTabIndex);
super.onSaveInstanceState(outState);
}
}
No problem with displaying the buttons and the tabs, it's just that the OnClickListener is not called when the program runs.
I'm quite new to android and java and I want to implement the following functions in action Bar:
TAB 1 : Displays ListFragment A and Listfragment B
TAB 2 : Displays ListFragment C and Listfragment D
I already made the code to display a view with ListFragment A and Listfragment B but without action Bar. I'm trying to integrate action bar with tabs and now it is not working and I'm not able to figure out what is wrong or find a post with a solution.
I'm using an activity for each Fragment.
At the moment, I can display one fragment in each tab with the action bar :
fragment A appears when I click in Tab 1
Fragment C appears when I click in Tab 2
My Problem is:
When I click on an item in Fragment A, Fragment B appears in a new View ( = without either action bar nor fragment A)
=> How should I do to display in the same view : Action Bar, Fragment A and Fragment B?
=> I don't understand really how I should configure action bar to appear on top of each view. Is it done in a separate xml? How is it configured? Should we call action bar on top of each activity?
=> I don't understand really why I need 4 levels of xml to display these fragments.
For my code, I used several tutorials from following links but now I'm not able to find an answer:
http://mobile.tutsplus.com/tutorials/android/android-sdk_fragments/
Adding tabs from http://www.devdiv.com/android/docs/guide/topics/ui/actionbar.html
dgn2_action_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#+id/fragment_place">
</LinearLayout>
</LinearLayout>
dgn2_synth_entry.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="fill_parent"
android:orientation="horizontal" >
<fragment
android:id="#+id/listFragment"
android:layout_width="150dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginTop="?android:attr/actionBarSize"
class="com.android.FragmentA" >
</fragment>
<fragment
android:id="#+id/detailSynthFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
class="com.android.FragmentB" >
<!-- Preview: layout=#layout/details -->
</fragment>
</LinearLayout>
dgn2_synth_detail_layout.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" >
<fragment
android:id="#+id/detailSynthFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.android.FragmentB" />
</LinearLayout>
dgn2_details.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" >
<ListView
android:id="#+id/resultFragmentView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="#ffffff"
/>
</LinearLayout>
Dgn2EntryActivity.java
public class Dgn2EntryActivity extends Activity implements Dgn2SynthListFragment.OnSheetSelectedListener
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dgn2_action_bar);
/* Setup Action Bar for tabs */
ActionBar mActionBar = getActionBar();
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
/* add a new tab and set its title text */
ActionBar.Tab tabSynthesis = mActionBar.newTab().setText(R.string.sSynthesisTab);
ActionBar.Tab tabParameter = mActionBar.newTab().setText(R.string.sParameterTab);
/* instantiate fragment for the tab */
ListFragment mSynthesisFragment = new FragmentA();
ListFragment mParamFragment = new FragmentC();
/* Set Listener on Tab Action */
tabSynthesis.setTabListener(new MyTabsListener(mSynthesisFragment));
tabParameter.setTabListener(new MyTabsListener(mParamFragment));
/* Add Tab in Action Bar */
mActionBar.addTab(tabSynthesis);
mActionBar.addTab(tabParameter);
}
public void onSheetSelected(String sheetID, FragmentB viewer)
{
if (viewer == null || !viewer.isInLayout())
{
/*initialise Fragment call */
Intent intent = new Intent(getApplicationContext(),FragmentBActivity.class);
intent.putExtra("value", sheetID);
startActivity(intent);
}
else
{
/* Update Fragment content after a click */
viewer.updateSheet(sheetID);
}
}
protected class MyTabsListener implements ActionBar.TabListener
{
private ListFragment mFragment;
public MyTabsListener(ListFragment mFragment)
{
this.mFragment = mFragment;
}
public void onTabSelected(Tab paramTab,
FragmentTransaction paramFragment)
{
paramFragment.add(R.id.fragment_place, mFragment, null);
}
public void onTabUnselected(Tab paramTab,
FragmentTransaction paramFragment)
{
paramFragment.remove(mFragment);
}
public void onTabReselected(Tab paramTab,
FragmentTransaction paramFragment)
{
}
}
}
FragmentBActivity.java
public class FragmentBActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.dgn2_synth_detail_layout);
/* get Sheet Label */
Bundle extras = getIntent().getExtras();
if (extras != null)
{
String sheetLabel = extras.getString("value");
FragmentB viewer = (FragmentB) getFragmentManager()
.findFragmentById(R.id.detailSynthFragment);
/*Update Fragment Viewer view content*/
viewer.updateSheet(sheetLabel);
}
}
}
FragmentA.java
public class FragmentA extends ListFragment
{
private OnSheetSelectedListener sheetSelectedListener;
public interface OnSheetSelectedListener
{
public void onSheetSelected(String sheetID, FragmentB viewer);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
String[] values = new String[] { GLOBAL_SYNTHESIS_LABEL, SYNTHESIS1_LABEL};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id)
{
String item = (String) getListAdapter().getItem(position);
FragmentB viewer = (FragmentB) getFragmentManager().findFragmentById(R.id.detailFragment);
sheetSelectedListener.onSheetSelected(item, viewer);
}
}
FragmentB.java
public class FragmentB extends ListFragment
{
Context mContext;
Dgn1DataListClass allResults = new Dgn1DataListClass();
String[] vIhmDgnVarNameList;
Dgn1ResultCouple[] results;
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
updateSheet(GLOBAL_SYNTHESIS_LABEL);
}
public void updateSheet(String sheetLabel)
{
mContext = getActivity();
ListView resultListView =(ListView)getView().findViewById(R.id.resultFragmentView);
if (sheetLabel == GLOBAL_SYNTHESIS_LABEL)
{
/* Displays A list in 2 columns */
vIhmDgnVarNameList = getResources().getStringArray(R.array.ihm_dgn_row1_array);
results = allResults.fillResults(vIhmDgnVarNameList);
ListItemAdapter2 mcqListAdapter = new ListItemAdapter2(mContext,R.layout.ihm_dgn_row_data,results);
setListAdapter(mcqListAdapter);
}
else if (sheetLabel == SYNTHESIS1_LABEL)
{
/* TODO */
}
}
public class ListItemAdapter2 extends ArrayAdapter<Dgn1ResultCouple>
{
/* Lot Of Code working*/
}
}
Thanks for your help