Overlapping of fragments when transiting on clicking on an item in RecyclerView of one fragment to another new fragment - android-fragments

I am new to android development. The problem is the RecyclerView populated using a firebase database is not replaced by a new fragment, rather the new fragment is on top, but clicking on another item of the recycler view still works, which I checked using a toast in the new fragment. I know that the next fragment is there because I have TextView at the bottom, which is visible on clicking on the recycler view Item.
Here is my code
adapter = new FirebaseRecyclerAdapter<Categories, CategoryViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull final CategoryViewHolder holder, int position, #NonNull Categories model)
{
Picasso.get().load(model.getImage()).placeholder(R.drawable.camera).into(holder.categoryImage, new Callback() {
#Override
public void onSuccess()
{
}
#Override
public void onError(Exception e) {
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
holder.categoryName.setText(model.getName());
holder.categoryImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), holder.categoryName.getText().toString(), Toast.LENGTH_SHORT).show();
// Intent intent = new Intent(getActivity(), ProductListActivity.class);
// startActivity(intent);
AppCompatActivity activity = (AppCompatActivity) view.getContext();
SearchFragment fragment = SearchFragment.newInstance(holder.categoryName.getText().toString());
FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.nav_host_fragment, fragment, SearchFragment.class.getSimpleName());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
The fragment I am using is also used for the navigation drawer using navController.
<?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:showIn="#layout/app_bar_main">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</RelativeLayout>
Edit: I have another recyclerView inside SearchFragment, which didn't show after I clicked an image in the RecyclerView(One which calls SearchFragment). But it showed after I minimized and opened the app again. I don't understand why that is happening.

I just found an easy way to move from one fragment to another without using FragmentManager. I hope this helps others, it worked for me. Initialize the NavController in the first fragment inside onCreateView
navController = Navigation.findNavController(getActivity(), R.id.nav_host_fragment);
And adding the following for transition
Bundle bundle = new Bundle();
bundle.putString("Category", holder.categoryName.getText().toString());
navController.navigate(R.id.nav_category_product_list, bundle);
to get the argument in the moving fragment type this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true); //To get menu items at the top
if (getArguments() != null) {
Category = getArguments().getString("Category");
}
}
Also, add this transition in Navigation graph XML
.
.
.
<fragment
android:id="#+id/nav_category"
android:name="com.grocery.admin.ui.category.CategoryFragment"
android:label="#string/menu_category"
tools:layout="#layout/fragment_category" >
<action
android:id="#+id/action_nav_category_to_nav_category_product_list"
app:destination="#id/nav_category_product_list" />
</fragment>
<fragment
android:id="#+id/nav_category_product_list"
android:name="com.grocery.admin.ui.category.CategoryProductFragment"
android:label="Product List"
tools:layout="#layout/fragment_category_product">
</fragment>
.
.
.

Related

Navigation Drawer opens to different fragments

I am a beginner when it comes to Android. I have spent hours reading tutorials, watching videos, and combing through stackoverflow trying to figure this out. Even with all the online resources available , I still can't figure this out.
I want my list view always on the main screen, but when I swipe I want the navigation drawer to slide in and display a different fragment depending on which item in the list view has been selected. For example if the user selected 'account', when they slide from the right the account fragment would display.
I've left in 'navList' and 'nav2List' for testing, but I would like these to be fragments.
XML
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<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"
tools:context=".MainActivity">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/bankMenu"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
</ListView>
</RelativeLayout>
<!-- Side navigation drawer UI -->
<ListView
android:id="#+id/navList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="right"
android:background="#ffeeeeee"/>
<ListView
android:id="#+id/nav2List"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="right"
android:background="#ffeeeeee"/>
</android.support.v4.widget.DrawerLayout>
JAVA
public class MainActivity extends AppCompatActivity {
private ListView menu;
private ListView mDrawerList;
private ListView secondDrawerList;
private ArrayAdapter<String> mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
menu = (ListView) findViewById(R.id.bankMenu);
mDrawerList = (ListView)findViewById(R.id.navList);
secondDrawerList = (ListView)findViewById(R.id.nav2List);
addBankingListItems(); // populate the banking items list
menu.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
// ListView Clicked item index
int itemPosition = position;
// ListView Clicked item value
String itemValue = (String) menu.getItemAtPosition(position);
// Show Alert
Toast.makeText(getApplicationContext(),
"Position :" + itemPosition + " ListItem : " + itemValue, Toast.LENGTH_LONG)
.show();
if (itemPosition < 4) { // TESTING FUNCTIONALITY
addDrawerItems();
} else {
addSecondDrawerItems();
}
}
});
}
---EDIT---
This issue has been resolved.
In the xml file, i changed the two ListViews to a RelativeView.
<RelativeLayout
android:id="#+id/frame_to_be_replaced"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_below="#+id/topRL"
android:background="#ffeeeeee">
</RelativeLayout>
In the MainActivity, I created a fragment manager, then after my switch statement, i replaced the frame with the required one. Hope this can help someone, send me a pm for more info.
FragmentManager fragmentManager = getFragmentManager();
switch (itemPosition) {
case 0:
fragment = MyFrag1.newInstance("", ""); // fragment declared above
break;
case 1:
fragment = MyFrag2.newInstance("", "");
break;
case 2: etc....
fragmentManager.beginTransaction()
.replace(R.id.frame_to_be_replaced, fragment)
.commit();

Android ,overlapping imageview android

I tried to display a small imageview above the big imageview .It worked fine.
But when I made the small imageview to appear in rounded shape, It is not showing up.. Your reply will be helpful
there is no error or warning or any crashing of avd .simply the small imageview is not showing
.xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:maxHeight="1000dp"
android:maxWidth="1000dp"
android:scaleType="fitXY"
android:src="#drawable/ciaz"
tools:ignore="ContentDescription" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/imageView1"
android:layout_centerHorizontal="true"
android:layout_marginBottom="14dp"
android:adjustViewBounds="true"
android:maxHeight="300dp"
android:maxWidth="300dp"
android:scaleType="fitXY"
android:src="#drawable/ac"
android:visibility="visible"
tools:ignore="ContentDescription,RtlHardcoded" />
</RelativeLayout>
mainactivity.java
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
im1 = (ImageView) findViewById(R.id.imageView1);
im2 = (ImageView) findViewById(R.id.imageView2);
im1.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
try
{
int action=arg1.getAction();
float x=(float)arg1.getX();
float y=(float)arg1.getY();
if(action==MotionEvent.ACTION_DOWN)
{
context = getApplicationContext();
duration = Toast.LENGTH_SHORT;
String g= x+" "+y;
Toast toast = Toast.makeText(context, g, duration);
toast.show();
if((x>0.0) && (x<100)&&(y>0.0) && (y<100))
{
im2.setVisibility(View.VISIBLE);
Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.ac);
roundedImage = new RoundedImageView(bm);
im2.setImageDrawable(roundedImage);
}
}
}
catch(Exception e)
{
Toast toast = Toast.makeText(context, "exception", duration);
toast.show();
}
return false;
}
});
}
enter code here
Make sure that if you are using relative layout, place big image view first and then after small age view. Otherwise big image view overlaps small image view. If that is not the case can u please give code snippet to help more and find out the issue ?
You are giving 1000 h and 1000 w for first image view, and using android:layout_alignBottom="#+id/imageView1" in second imageview. So it goes out of ur device screen. Use match parent for first image view and remove alignbottom.

getChildFragmentManager() and viewpager

I have the same problem as Navigating back to FragmentPagerAdapter -> fragments are empty but would like some clarification on the solution of using getChildFragmentManager().
This solution uses getChildFragmentManager(), the manager for fragments inside this Fragment(OuterFragment, which has the viewpager). InnerFragment is a page inside OuterFragment. When someone clicks the listview in InnerFragment, I want InnerFragment2 to replace InnerFragment. What do the xml and fragment managers look like?
fragment_outer.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/vpPager"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_header"
android:layout_gravity="top"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingBottom="4dp"
android:paddingTop="4dp" />
<FrameLayout
android:id="#+id/inner_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.view.ViewPager>
OuterFragment.java:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_outer, container, false);
vpPager = (ViewPager) v.findViewById(R.id.vpPager);
FragmentManager cfManager = getChildFragmentManager();
adapterViewPager = new MyPagerAdapter(cfManager);
vpPager.setAdapter(adapterViewPager);
return v;
}
public static class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public int getCount() {
return 2;
}
// Returns the fragment to display for that page
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return InnerFragment.newInstance(false);
case 1:
return InnerFragment.newInstance(true);
default:
return null;
}
}
InnerFragment shows up as a fragment inside OuterFragment, which has the viewpager. InnerFragment has a listview that when clicked, should replace InnerFragment with InnerFragment2.
InnerFragment.java:
FragmentManager fm = getChildFragmentManager();
fm = fm.beginTransaction();
ft.addToBackStack(null);
ft = ft.replace(R.id.inner_content,
InnerFragment2.newInstance(someArg));
ft.commit();
This throws an error saying InnerFragment2 does not recognize view R.id.inner_content.
Not only should InnerFragment2 replace InnerFragment, but when InnerFragment2 is shown and it's button is clicked, I want InnerFragment2 replaced with InnerFragment3. I basically want to use inner_content as an inner container and keep adding fragments to a backstack for appropriate back behavior.
Do I getChildFragmentManager() or getFragmentManager() each time I add to my fragment backstack, what does the xml pattern look like, because having one framelayout in my outerfragment isn't doing it.
public void setupViewPager(ViewPager viewPager) {
FragmentManager cfManager=getChildFragmentManager();
viewPagerAdapter = new ViewPagerAdapter(cfManager);
// viewPagerAdapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
viewPagerAdapter.addFragment(new EntertainmentWallpaperFragment(), getString(R.string.title_entertainment_wallpapers));
viewPagerAdapter.addFragment(new EntertainmentMusicFragment(), getString(R.string.title_entertainment_music));
viewPagerAdapter.addFragment(new EntertainmentGamesFragment(), getString(R.string.title_entertainment_games));
viewPagerAdapter.addFragment(new EntertainmentEBooksFragment(), getString(R.string.title_entertainment_ebooks));
viewPagerAdapter.addFragment(new EntertainmentAppsFragment(), getString(R.string.title_entertainment_apps));
viewPager.setAdapter(viewPagerAdapter);
}
I hope this helps. I had the same problem where the fragments apear but once you go back they dissapear and find an empty fragent. Commnented the line that I had first implemented which after updating the fragment manager I was able to enjoy free smooth scroll.

Fragment seems to inflate wrong view

I'm currently trying to program an Android Launcher with Fragments but I have problems with the Views on the Fragments.
I have a Dock-Fragment with a Dock-Controller which allow the user to change fragments, such as apps menu, settings fragment etc. The Dock is displayed on the buttom of the display, the Fragments(apps menu, settings fragment) should be displayed above the Dock.
The problem is, that the apps menu is not shown in its associated Fragment but rather in the Dock Fragment behind the dock icons,... So I guess, the app menu fragment gets the wrong view in its onCreateView()-Method, but I don't get why.
This is the code of the MainActivity that extends from FragmentActivity. I add the fragments to the manager.
private void addDockToManager() {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(dbConnection.getLayout(DOCK_TAG), dockController.getFragment(), DOCK_TAG);
ft.commit();
}
private void addPluginsToManager() {
FragmentManager fm = null;
FragmentTransaction ft = null;
for(String key : controllerMap.keySet()) {
fm = getSupportFragmentManager();
ft = fm.beginTransaction();
FrameController controller = null;
if ((controller = controllerMap.get(key)) != null) {
ft.add(dbConnection.getLayout(key), controller.getFragment(), key);
if (key.equals(standardFrame))
ft.addToBackStack(key);
}
ft.commit();
fm.executePendingTransactions();
}
fm = getSupportFragmentManager();
ft = fm.beginTransaction();
for(String key : controllerMap.keySet()) {
if (controllerMap.get(key) != null && !key.equals(standardFrame)) {
ft.hide(fm.findFragmentByTag(key));
}
}
ft.commit();
}
The layouts are hardcoded at the moment in dbConnection:
public int getLayout(String name) {
int layout = -1;
switch(name) {
case "app_menu" : layout = R.id.fl_app_menu;
case "settings" : layout = R.id.fl_settings;
case "dock" : layout = R.id.fl_dock;
}
return layout;
}
The MainActivity's xml looks like that:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/rl_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.activity.MainActivity"
tools:ignore="MergeRootFrame" >
<FrameLayout
android:id="#+id/fl_settings"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_above="#+id/fl_dock"
android:background="#00ffffff" >
</FrameLayout>
<FrameLayout
android:id="#+id/fl_app_menu"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_above="#+id/fl_dock"
android:background="#00ffffff" >
</FrameLayout>
<FrameLayout
android:id="#+id/fl_dock"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" >
</FrameLayout>
</RelativeLayout>
The xml of the apps menu is a gridview and looks like that:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gv_apps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="6"
android:gravity="center"
android:columnWidth="50dp"
android:stretchMode="columnWidth" >
</GridView>
The App Fragment looks like that:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup group,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.external_apps, group, false);
layout = (GridView) view.findViewById(R.id.gv_apps);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
GridViewAdapter gridViewAdapter = new GridViewAdapter((AppMenuController) myController, apps);
((GridView) layout).setAdapter(gridViewAdapter);
}
And the getView Method of the GridViewAdapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(controller.getMainActivity().getApplicationContext());
imageView.setImageDrawable(buttons.get(position).getIcon());
imageView.setLayoutParams(new GridView.LayoutParams(65, 65));
return imageView;
}
I hope what I mentioned is enough to resolve the problem. I am searching the web for hours but I found no solution.
It's a much simpler problem than that I think.
public int getLayout(String name) {
int layout = -1;
switch(name) {
case "app_menu" : layout = R.id.fl_app_menu;
case "settings" : layout = R.id.fl_settings;
case "dock" : layout = R.id.fl_dock;
}
return layout;
}
Should be:
public int getLayout(String name) {
int layout = -1;
switch(name) {
case "app_menu" :
layout = R.id.fl_app_menu;
break;
case "settings" :
layout = R.id.fl_settings;
break;
case "dock" :
layout = R.id.fl_dock;
break;
}
return layout;
}
Because switch-case structure is still essentially just an organized goto, and not actually an if-else structure, aka if you don't break out, then all cases will run sequentially.
I found the problem. And it was in a part of the code I never expected it to be.
The Dummy-Switch-Case in dbConnection caused it. Seemingly Strings aren't compared by value but rather by reference in such a Switch-Case. So it always chose the dock container layout to be associated with the app menu in the fragment manager,...

Click on a specific part of an ImageView

I would like to be able to touch a specific part of an ImageView and display a toast.
Here is my xml file "dessintest.xml" :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/relative1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<ImageView
android:id="#+id/imageview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/dessin1"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
>
</ImageView>
<ImageButton
android:id="#+id/imageButton1"
android:background="#00000000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/image" />
</RelativeLayout>
Then here is my main file "DessinTest.java" :
public class DessinTest extends Activity {
ImageButton imageButton;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.dessintest);
addListenerOnButton();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.dessin1);
TouchImageView touch = new TouchImageView(this);
touch.setImageBitmap(bm);
touch.setMaxZoom(4f); //change the max level of zoom, default is 3f
setContentView(touch);
}
public void addListenerOnButton() {
imageButton = (ImageButton) findViewById(R.id.imageButton1);
imageButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Toast.makeText(DessinTest.this,"Click !", Toast.LENGTH_SHORT).show();
}
});
}
}
When I try that, I can zoom the ImageView but I cannot see the ImageButton.
When I delete this bit of code (the one for the zooming of my ImageView) :
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.dessin1);
TouchImageView touch = new TouchImageView(this);
touch.setImageBitmap(bm);
touch.setMaxZoom(4f); //change the max level of zoom, default is 3f
setContentView(touch);
it is working, I can see the ImageButton and click on it.
What I would like is to have both functionnalities, click and zoom.
Thanks !
OK I resolved my problem by using this sample :
https://github.com/chrisbanes/PhotoView/blob/master/sample/src/uk/co/senab/photoview/sample/SimpleSampleActivity.java
I can now zoom and touch/detect specific parts of the screen. It works very well !

Resources