I'm trying to make an app (for learning purposes) where I have a few tabs with scrollable content.
I have a collapsing app bar with a ViewPager for the main layout and three identical layouts with a TextView inside a NestedScrollView where the only difference is the image on top of the text. I also have three fragment classes with the same code inside. Everything worked fine.
But since I'm using the same layout in each tab, I thought that instead of a xml file and a java class for each tab, I could just have one of each and then somehow change the content for each tab inside my Adapter.
So I tried to just create a method to do that inside my tabFragment class. But I can't seem to find a way to modify the TextView. I keep getting a NullPointerException every time.
What am I missing?
Is my approach wrong? If so, what would be a better one? How do I solve this?
Thank you in advance :)
Here's my fragment class right now (the only one remaining ):
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import com.example.tablayoutwithscrollview.R;
public class TabFragment extends Fragment {
private TextView textView;
private int text, image;
public TabFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.tab1, container, false);
//textView = view.findViewById(R.id.textView);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
textView = getView().findViewById(R.id.textView);
}
public void setTabContent(int text, int image)
{
textView.setText(text);
textView.setCompoundDrawablesWithIntrinsicBounds(0,image,0,0);
}
}
My adapter class:
import android.content.Context;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.example.tablayoutwithscrollview.Tabs.TabFragment;
public class MyAdapter extends FragmentPagerAdapter {
private static int tabCount;
Context context;
public MyAdapter(FragmentManager fm, int tabCount, Context context){
super(fm);
this.tabCount = tabCount;
this.context = context;
}
#Override
public Fragment getItem(int position) {
TabFragment fragment;
switch (position)
{
case 0:
fragment = new TabFragment();
fragment.setTabContent(R.string.lorem_ipsum, R.drawable.jackfruit);
return fragment;
case 1:
fragment = new TabFragment();
fragment.setTabContent(R.string.lorem_ipsum, R.drawable.guava);
return fragment;
case 2:
fragment = new TabFragment();
fragment.setTabContent(R.string.lorem_ipsum, R.drawable.pomegranate);
return fragment;
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position)
{
switch (position)
{
case 0:
return context.getString(R.string.tab1_title);
case 1:
return context.getString(R.string.tab2_title);
case 2:
return context.getString(R.string.tab3_title);
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
MainActivity:
package com.example.tablayoutwithscrollview;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout = findViewById(R.id.tabLayout);
viewPager = findViewById(R.id.viewPager);
populatesTabLayout(tabLayout);
MyAdapter myAdapter = new MyAdapter(getSupportFragmentManager(), tabLayout.getTabCount(), this);
viewPager.setAdapter(myAdapter);
tabLayout.setupWithViewPager(viewPager);
}
private void populatesTabLayout(TabLayout tabLayout)
{
for (int i = 0; i<3; i++)
{
tabLayout.addTab(tabLayout.newTab());
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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/coordLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/collapseToolBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="#+id/toolbar">
<ImageView
android:id="#+id/imageView7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="#drawable/strawberry" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"></androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:visibility="visible" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And my tab layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/tabNestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableTop="#drawable/jackfruit"
android:text="#string/lorem_ipsum" />
</androidx.core.widget.NestedScrollView>
Here's how it's supposed to work (from before when each tab had a fragment class and a layout file):
The problem is that the created TabFragment instance has not been attached to the activity yet, therefore the textView does not inflated at that point.
You should pass the text to the TabFragment instance as an argument in the MyAdapter#getItem(..) method.
...
case 0:
fragment = new TabFragment();
Bundle args = new Bundle();
args.putString("key", textString);
fragment.setArguments(args);
return fragment
...
After that set the text for the TextView instance in the onViewCreated(...) method:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
textView = getView().findViewById(R.id.textView);
textView.setText(getArguments().getString("key"));
}
Or you can see a nice example at the Android Reference.
Related
i am using the new android viewpager2, but when i load different fragments, the viewpager2 shows only the same fragments..
Is this an error? in the older viewpager everything worked.
As you can see here in the images, the android app load the same fragments.
In the viewPagerAdapter I load or create for each position a different fragment
Code ViewPagerAdaptor
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(#NonNull FragmentActivity fragmentActivity)
{
super(fragmentActivity);
}
#NonNull
#Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return new page1();
case 1:
return new page2();
default:
return new pageDefault();
}
}
#Override
public int getItemCount() {return 3; }
}
The MainActivity.class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout = findViewById(R.id.tabs);
viewPager2 = findViewById(R.id.view_pager);
ViewPagerAdapter adapter = new ViewPagerAdapter(this);
viewPager2.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager2,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
tab.setText("Tab " + (position + 1));
}
}).attach();
}
here come the fragments
fragment_page1
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_page1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".page1">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:textSize="20sp"
android:textStyle="bold"
android:text="This is Page 0" />
</FrameLayout>
and fragment_page2
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".page2">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold"
android:text="This is Page 02"
android:background="#color/red_100"/>
</FrameLayout>
and the java code of page1.java
package com.example.demo_viewpager2;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class page1 extends Fragment {
public page1() {
// Required empty public constructor
}
public static page1 newInstance() {
page1 fragment = new page1();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_page1, container, false);
}
}
After trying the code provided and add the missing files, i am unable to replicate your issue and is working fine on my testing.
ViewPagerAdapter.java file
package com.example.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.example.fragment.page1;
import com.example.fragment.page2;
import com.example.fragment.pageDefault;
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(#NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
#NonNull
#Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return new page1();
case 1:
return new page2();
default:
return new pageDefault();
}
}
#Override
public int getItemCount() {
return 3;
}
}
MainActivity.java file
package com.example.view;
import android.app.Activity;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.widget.ViewPager2;
import com.example.R;
import com.example.adapter.ViewPagerAdapter;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = findViewById(R.id.tabs);
ViewPager2 viewPager2 = findViewById(R.id.view_pager);
ViewPagerAdapter adapter = new ViewPagerAdapter(this);
viewPager2.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager2,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
tab.setText("Tab " + (position + 1));
}
}).attach();
}
}
page1.java file
public class page1 extends Fragment {
public page1() {
// Required empty public constructor
}
public static page1 newInstance() {
page1 fragment = new page1();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_page1, container, false);
}
}
page2.java file
public class page2 extends Fragment {
public page2() {
// Required empty public constructor
}
public static page2 newInstance() {
page2 fragment = new page2();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_page2, container, false);
}
}
pageDefault.java file
public class pageDefault extends Fragment {
public pageDefault() {
// Required empty public constructor
}
public static pageDefault newInstance() {
pageDefault fragment = new pageDefault();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_page_default, container, false);
}
}
main_activity.xml file
<?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">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
fragment_page1.xml file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_page1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="This is Page 0"
android:textSize="20sp"
android:textStyle="bold" />
</FrameLayout>
fragment_page2.xml file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold"
android:text="This is Page 02"
android:background="#android:color/holo_red_light"/>
</FrameLayout>
fragment_page_default.xml file
<?xml version="1.0" encoding="utf-8"?>
<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">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold"
android:text="This is Page Default"/>
</FrameLayout>
Output:
thank you, this workes really fine.
there was an typo error in the inflate of page2 to the page1
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_page1, container, false);
}
I am trying to create tabs in my layout. But instead of showing tab it is showing the below screen in design:
Below is the code:
**activity_mail.xml**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="200dp"
android:id="#+id/appBarLayout2">
<com.google.android.material.tabs.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"/>
</android.support.design.widget.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/white"/>
</LinearLayout>
MainActivity.java
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
public class MainActivity extends AppCompatActivity {
/* private TabAdapter adapter;
private TabLayout tabLayout;
private ViewPager viewPager;*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new TabAdapter(getSupportFragmentManager(),
MainActivity.this));
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
}
}
Tab1Fragment.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
public class Tab1Fragment extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
private int mPage;
public static Tab1Fragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
Tab1Fragment fragment = new Tab1Fragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) view;
textView.setText("Fragment #" + mPage);
return view;
}
}
TabAdapter.Java
import android.content.Context;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
public class TabAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Tab1", "Tab2", "Tab3" };
private Context context;
public TabAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
return Tab1Fragment.newInstance(position + 1);
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.PlaceholderFragment">
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:text="#string/sparta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1" />
</androidx.constraintlayout.widget.ConstraintLayout>
Also when trying to run it in my mobile, it is showing error something like:
android.widget.RelativeLayout cannot be cast to android.widget.TextView
Please suggest the way to solve this issue.
After androidX, support library are removed,
so you need to use material design which help you.
Replace your appbar with below code
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="200dp"
android:id="#+id/appBarLayout2">
this will help you.
You're using deprecated design support AppBarLayout, You need to replace it with androidx library , so replace android.support.design.widget.AppBarLayout with com.google.android.material.appbar.AppBarLayout in your layout.
<?xml version="1.0" encoding="utf-8"?><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="200dp">
<com.google.android.material.tabs.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/white" />
</LinearLayout>
For the android.widget.RelativeLayout cannot be cast to android.widget.TextView, please post the entire stack trace.
UPDATE
tab names are not coming. only green background of the tablayout is shown.
this is odd behavior, as I you already override getPageTitle in the adapter.. I just suggest not to use a hard-coded array of Strings in the adapter, instead add the tab titles in the strings.xml
Strings.xml
<resources>
<string name="tab1">Tab1</string>
<string name="tab2">Tab2</string>
<string name="tab3">Tab3</string>
</resources>
Adapter
public class TabAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
// private String tabTitles[] = new String[] { "Tab1", "Tab2", "Tab3" };
private int[] tabTitles = new int[]{R.string.tab1, R.string.tab2, R.string.tab3};
private Context context;
public TabAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
return Tab1Fragment.newInstance(position + 1);
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
// return tabTitles[position];
return context.getString(tabTitles[position]);
}
}
Please have a look at this question that might be relevant.
UPDATE 2
Try to add those listeners
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new TabAdapter(getSupportFragmentManager(),
MainActivity.this));
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
// listeners
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
}
if not working , try to set the current item of the ViewPager
viewPager.setCurrentItem(itemPosition);
I know there are a bunch of answers on StackOverflow regard my question but none of them fixed my problem as my Fragments are static.
I have two fragments in my activity. The second one is covering the first one and this is the fragment that will be shown/hidden.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FeedActivity">
<fragment
android:id="#+id/listViewFragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="com.me.cscomponents.fragFeed.FeedFragment"
tools:layout="#layout/fragment_feed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/gh1"
app:layout_constraintBottom_toBottomOf="parent"/>
<fragment
android:id="#+id/playerViewFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.me.cscomponents.fragPlayer.PlayerFragment"
tools:layout="#layout/fragment_player"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/gh1"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
In the TV app, both of Fragments are visible side by side. However, in the mobile app, listViewFragment is visible by default and playerViewFragment displays when an item in listViewFragment clicks by the user. When the user clicks on the Back button then this view becomes hidden (and therefore listViewFragment becomes visible).
This is my code (but it doesn't work as I expect):
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_feed)
listFragment = supportFragmentManager.findFragmentById(R.id.listViewFragment) as FeedFragment
playerFragment = supportFragmentManager.findFragmentById(R.id.playerViewFragment) as PlayerFragment
val d1: Disposable = listFragment.onClickSubject
.subscribe {
showOrHidePlayerFragment(true)
playerFragment.streamCamera(it.camFeedUrl)
}
cd.add(d1)
showOrHidePlayerFragment(false)
}
private fun showOrHidePlayerFragment(isVisible: Boolean) {
val fm = supportFragmentManager.beginTransaction()
if (isVisible) fm.show(playerFragment) else fm.hide(playerFragment)
fm.commit()
}
The problem is playerFragment is still visible when I launch the activity. So, I have no idea how to fix the issue and what is the cause of the problem.
My current workaround is to surround my playerFragment in a FrameLayout and make this view visible/invisible. This approach works fine.
I think few stuff went wrong with your coding. Try to avoid hard coding fragment like
android:name="com.me.cscomponents.fragFeed.FeedFragment"
Based on your question i prepared a something for you. I just implemented two button click rather publishing a list. Passed an int (you can pass according to your need.). I tried to follow few best practices. For simplicity i used LinearLayout & RelativeLayout.
activity_test.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TestActivity">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
TestActivity.java
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class TestActivity extends AppCompatActivity implements FeedFragment.OnItemClickedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, FeedFragment.getInstance(), FeedFragment.TAG).commit();
}
#Override
public void onButtonClicked(int position) {
getSupportFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.fragment_container, PlayerFragment.getInstance(position), PlayerFragment.TAG).commit();
}
#Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof FeedFragment) {
FeedFragment feedFragment = (FeedFragment) fragment;
feedFragment.setOnButtonClickedListener(this);
}
}
}
fragment_feed.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">
<Button
android:id="#+id/button_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Feed 1" />
<Button
android:id="#+id/button_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Feed 2"/>
</LinearLayout>
FeedFragment.java
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class FeedFragment extends Fragment {
public static final String TAG = FeedFragment.class.getSimpleName();
View view;
OnItemClickedListener callback;
Button buttonOne;
Button buttonTwo;
public static FeedFragment getInstance(){
FeedFragment fragment = new FeedFragment();
return fragment;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.feed_fragment, container, false);
buttonOne = view.findViewById(R.id.button_one);
buttonTwo = view.findViewById(R.id.button_two);
init();
return view;
}
private void init() {
buttonOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onButtonClicked(1);
}
});
buttonTwo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onButtonClicked(2);
}
});
}
public void setOnButtonClickedListener(OnItemClickedListener callback) {
this.callback = callback;
}
public interface OnItemClickedListener {
public void onButtonClicked(int position);
}
}
fragment_player.xml
<?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">
<TextView
android:id="#+id/demo_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
PlayerFragment.java
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class PlayerFragment extends Fragment {
public static final String TAG = PlayerFragment.class.getSimpleName();
private static final String ARG_POSITION = "position";
private View view;
private TextView demoTextView;
private int position;
public static PlayerFragment getInstance(int position){
PlayerFragment fragment = new PlayerFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getArguments() != null ){
position = getArguments().getInt(ARG_POSITION);
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_player, container, false);
demoTextView = view.findViewById(R.id.demo_text_view);
init();
return view;
}
private void init() {
demoTextView.setText("Player Fragment, clicked position "+ position);
}
}
Hope it will help you. Thanks.
The tag fragment has an id, the Fragment root view will have that id.
So it will be
findViewById(R.id.oneFragment).setVisibility(View.GONE);
By example, if FragmentOne use the following layout:
<LinearLayout>
<!--Chile Viiews-->
</LinearLayout>
And you are using the tag fragment, like this:
<fragment
id=oneFragment
name=FragmentOne/>
Then that linear layout will end up having oneFragment as id. That is how the tag fragment works after the fragment is attached the tag fragment id is assigned to the root view o the fragment. You can read more here.
Another way to do this is to use the fragment manager, here is a one-liner:
getSupportFragmentManager().findFragmentById(R.id.fragment).getView().setVisibility(View.GONE);
I am trying to show AutoCompleteTextView from a fragment. I have three fragments, so i use ViewPager to show the Fragement on MainActivity. I am able to type in the AutocompleteTextview, but the suggestions are not showing up in the mainActivity.
I tried with simple string array, but it doesn't show up. anyone have come across this issue. help me please.
Thanks in advance.
this is my code in the fragment:
ArrayAdapter<String> adapter= new ArrayAdapter<String> getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, somestring);
final AutoCompleteTextView textView = (AutoCompleteTextView) v.findViewById(R.id.listview4);
textView.setThreshold(1);
textView.setAdapter(adapter);
this is my mainActivity callout
tabLayout = (TabLayout)findViewById(R.id.tabLayout);
viewPAger = (ViewPager)findViewById(R.id.viewPager);
viewPagerAdapter=new ViewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragments(new Home() ,"HOME");
viewPAger.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPAger);
this is my viewpage adapter
package gt.transit;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
public class ViewPagerAdapter extends FragmentPagerAdapter {
ArrayList<Fragment> fragments = new ArrayList<>();
ArrayList<String> TabTitles = new ArrayList<>();
public void addFragments (Fragment fragments, String titles){
this.fragments.add(fragments);
this.TabTitles.add(titles);
}
public ViewPagerAdapter(FragmentManager fm){
super(fm);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
return TabTitles.get(position);
}
}
this my XML layout in main activity
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="gt.transit.MainActivity"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/appbar"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<include
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentTop="true"
layout="#layout/toolbar_layout" />
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tabLayout"
app:tabMode="fixed"
app:tabGravity="fill"
style="#style/MyCustomTabLayout" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/viewPager"
android:layout_below="#+id/appbar"
android:background="#e99d9d"
>
</android.support.v4.view.ViewPager>
</RelativeLayout>
Hi all,
thanks for your help. I was able solve the issue.
It's my bad i did not return view properly.
wrong code:
return inflater.inflate(R.layout.fragment_bookmark, container, false
corrected code:
return v;
This is my working code for an AutoCompleteTextView dialog fragment
public class MyAutoCompleteFragment extends DialogFragment implements OnEditorActionListener{
private EditDialogListener mCallback;
public static MyAutoCompleteFragment newInstance(Bundle fB){
MyAutoCompleteFragment eDialog = new MyAutoCompleteFragment();
eDialog.setArguments(fB);
return eDialog;
}
public interface EditDialogListener {
void onFinishEditDialog(String inputText, int flag);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (EditDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement onFinishEditDialog");
}
this.setCancelable(false);
}
private AutoCompleteTextView mAutoComp;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String[] lista = getArguments().getStringArray("listagem");
View view = inflater.inflate(R.layout.autodialog, container);
mAutoComp = (AutoCompleteTextView)view.findViewById(R.id.autodlg);
mAutoComp.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, lista));
//fill the text view with something already typed
if(getArguments().getString("digitado").length()>0) mAutoComp.setText(getArguments().getString("digitado"));
getDialog().setTitle(getArguments().getString("titulo"));
getDialog().setCancelable(false);
mAutoComp.requestFocus();
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
mAutoComp.setOnEditorActionListener(this);
view.setMinimumWidth(500);
return view;
}
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (EditorInfo.IME_ACTION_DONE == actionId) {
mCallback.onFinishEditDialog(mAutoComp.getText().toString(), 0);
mAutoComp.setText("");
getDialog().dismiss();
MyAutoCompleteFragment.this.dismiss();
}
return false;
}
R.layout.autodialog:
<?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"
>
<AutoCompleteTextView
android:id="#+id/autodlg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:completionThreshold="2"
android:inputType="textCapCharacters"
android:maxLines="1"
/>
</LinearLayout>
How you can call it from activity:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Bundle args= new Bundle(); args.putStringArray("listagem", list); args.putString("digitado", typed); args.putString("titulo", title);
MyAutoCompleteFragment frag = MyAutoCompleteFragment.newInstance(args);
frag.show(ft, "autodialog");
Don't forget to implement the callback in the activity:
#Override
public void onFinishEditDialog(String inputText, int flag) {
}
You can try in the view pager:
#Override
public Fragment getItem(int position) {
Bundle args= new Bundle();
switch (position) {
case 0:
args.putStringArray("listagem", listx); args.putString("digitado", typedx); args.putString("titulo", titlex);
break;
case 1:
args.putStringArray("listagem", listy); args.putString("digitado", typedy); args.putString("titulo", titley);
break;
}
return MyAutoCompleteFragment.newInstance(args);
}
And change the MyAutoCompleteFragment to extends Fragment.
i have a problem with ActionBarActivity and ViewPager.
On my "main-activity" which is a ActionBarActivity i have some tabs, which are fragments.
I want to implement the "swipe-feature" between these tabs.
I've already read the following tutorial:
http://developer.android.com/training/implementing-navigation/lateral.html
Actually i have implemented the whole code, but my app wont work. :(
There is no "swipe-feature" between the tabs.
Here is my code of the main-activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hauptmenue_extended);
try {
actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// ViewPager ...
pagerAdapter = new CollectionPagerAdapter(
getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(1);
viewPager
.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// Add all tabs to the actionbar...
Tab tabB = actionBar.newTab();
tabB.setText("Home");
tabB.setIcon(R.drawable.icon_home);
tabB.setTabListener(new TabListener<Startmenue_activity>(this,
"Start", Startmenue_activity.class, viewPager));
actionBar.addTab(tabB);
Tab tabA = actionBar.newTab();
tabA.setText("");
tabA.setIcon(R.drawable.icon_nachrichten_sel);
tabA.setTabListener(new TabListener<Nachrichten_activity>(this,
"News", Nachrichten_activity.class, viewPager));
actionBar.addTab(tabA);
Tab tabC = actionBar.newTab();
tabC.setText("");
tabC.setIcon(R.drawable.icon_favoriten);
tabC.setTabListener(new TabListener<Favoriten_activity>(this,
"Favs", Favoriten_activity.class, viewPager));
actionBar.addTab(tabC);
And my adapter looks like this:
public class CollectionPagerAdapter extends FragmentPagerAdapter {
final int NUM_ITEMS = 3; // number of tabs
List<Fragment> fragments = new ArrayList<Fragment>();
public Fragment getItem(int pos) {
return fragments.get(pos);
}
public void addFragment(Fragment f) {
fragments.add(f);
}
public CollectionPagerAdapter(FragmentManager fm) {
super(fm);
Fragment home_Fragment = new Startmenue_activity();
addFragment(home_Fragment);
Fragment news_Fragment = new Nachrichten_activity();
addFragment(news_Fragment);
Fragment favoriten_Fragment = new Favoriten_activity();
addFragment(favoriten_Fragment);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
}
Oh and my XML of the main-activity looks like this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Hauptmenue_extended" >
<!-- The ViewPager -->
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- The main content view -->
<FrameLayout
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#fff"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.view.ViewPager>
</android.support.v4.widget.DrawerLayout>
There's a bunch of things that I don't fully understand about your code, for example, why are you putting a ListView inside the ViewPager?. Anyways if you want to implement some tabs with the swipe feature. Here is how do it:
First the xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</android.support.v4.view.ViewPager>
Now the activity:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new SampleAdapter(this, getSupportFragmentManager()));
}
}
The adapter:
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
public class SampleAdapter extends FragmentStatePagerAdapter {
Context ctxt = null;
public SampleAdapter(Context ctxt, FragmentManager mgr) {
super(mgr);
this.ctxt = ctxt;
}
#Override
public int getCount() {
return 3;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new SimpleFragment("Hi");
case 1:
return new SimpleFragment("There");
case 2:
return new SimpleFragment("Fella");
}
return null;
}
#Override
public String getPageTitle(int position) {
switch (position) {
case 0:
return "First Tab";
case 1:
return "Second Tab";
case 2:
return "Third Tab";
}
return null;
}
}
And the SimpleFragment:
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
#SuppressLint("ValidFragment")
public class SimpleFragment extends Fragment {
String text;
public SimpleFragment(String string) {
text = string;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment, container, false);
TextView textview = (TextView) root.findViewById(R.id.textView1);
textview.setText(text);
return root;
}
}
And the fragment.xml:
<?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" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
Hope this helps :)
Try this out. But I've not tested it.
http://wptrafficanalyzer.in/blog/swipable-navigation-tabs-using-actionbarcompat-library/