I'm trying to replace a fragment with a another fragment with the following lines of code:
FragmentTransaction ft = Activity.FragmentManager.BeginTransaction();
UploadCompleted ucompleted = new UploadCompleted();
ft.Replace(Resource.Id.CameraFragmentContainer, ucompleted, "uploadcompleted");
ft.AddToBackStack(null);
ft.Commit();
The fragment is being replaced inside another fragment which uses the Activity's fragment manager. The issue is that the OnCreate and OnCreateView methods of the replaced fragment aren't invoked and an old instance of fragment (the fragment which was instantiated the first time I replaced it) get's instantiated which is why I'm not able to pass any new values to the replaced fragment. Any idea what I'm doing wrong? I'm new to android development so my knowledge of fragments isn't that great.
As per your logic, OnCreate and OnCreateView of the new Fragment should get invoked. It is a good practice to do FragmentTransaction at Activity level rather than, at Fragment level. In the above snippet you are creating an instance of the new Fragment from within the already displayed Fragment and replacing itself from the parent Activity. This is not a recommended approach. I would suggest the following change.
public class ParentActivity:Activity
{
public void ChangeToUploadCompleted()
{
FragmentTransaction ft = FragmentManager.BeginTransaction();
UploadCompleted ucompleted = new UploadCompleted();
ft.Replace(Resource.Id.CameraFragmentContainer, ucompleted, "uploadcompleted");
ft.AddToBackStack(null);
ft.Commit();
}
}
public FirstFragment:Fragment
{
void CaptureCompleted ()
{
((ParentActivity)Activity).ChangeToUploadCompleted();
}
}
This is the good practice to switch fragments. This might fix your problem too
ft.Replace(Resource.Id.CameraFragmentContainer, ucompleted, "uploadcompleted");
In this R.id is the layout that you place in Fragment Activity or Activity and UploadCompleted is Fragment class which you want to replace so use xml like this in FRagmentActivity or ACtivity class
<?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"
android:orientation="vertical">
<LinearLayout
android:id="#+id/lin"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</LinearLayout>
when you want to replace use this
FragmentTransaction ft = Activity.FragmentManager.BeginTransaction();
UploadCompleted ucompleted = new UploadCompleted();
ft.Replace(Resource.Id.lin, ucompleted, "uploadcompleted");
ft.AddToBackStack(null);
ft.Commit();
Related
How can you set AnimateLayoutChanges to True via C# in Xamarin.Android for a linear layout? I cannot use an xml resource file when building this custom view. The xml for this linear layout would be this:
<LinearLayout
android:orientation="vertical"
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:id="#+id/linearLayoutOne"
android:layout_weight="1"/>
All of the other attributes can be set via C# via the following:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.WrapContent, 1);
linearLayoutOne = new LinearLayout(Context);
linearLayoutOne.Orientation = Orientation.Vertical;
linearLayoutOne.LayoutParameters = layoutParams;
linearLayoutOne.SetMinimumHeight(25);
linearLayoutOne.SetMinimumWidth(25);
So how in the world do you set AnimateLayoutChanges in C#?
The C# equivalent of setting that is:
linearLayoutOne.LayoutTransition = new LayoutTransition();
linearLayoutOne.LayoutTransition.EnableTransitionType(LayoutTransitionType.Changing);
I made a Custom Layout to add a badge to a tab on Android. This badge is a TextView.
How do I bind this component?
It's possible?
My custom badge layout:
<LinearLayout
android:id="#+id/badgeCotainer"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="90dp"
android:background="#drawable/notifications_background"
android:gravity="center"
android:layout_gravity="right"
android:minWidth="16dp">
<TextView
android:id="#+id/badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textColor="#011f7a"
android:textSize="10sp"
android:text="0"
app:MvxBind="Text ContMaterial"/>
</LinearLayout>
My Activity: use MvxViewPagerFragmentInfo
private void InitTabs()
{
var viewPager = FindViewById<ViewPager>(Resource.Id.materiais_viewpager);
if (viewPager != null)
{
var fragments = new List<MvxViewPagerFragmentInfo>
{
new MvxViewPagerFragmentInfo("Requisição",
typeof(CadastraRequisicaoFragment), ViewModel),
new MvxViewPagerFragmentInfo("Materiais",
typeof(ListaMateriaisFragment), ViewModel),
};
viewPager.Adapter = new MvxCachingFragmentStatePagerAdapter(this, SupportFragmentManager, fragments);
}
var tabLayout = FindViewById<TabLayout>(Resource.Id.requisicao_tabs);
tabLayout.SetupWithViewPager(viewPager);
tabLayout.GetTabAt(1).SetCustomView(Resource.Layout.tab_header_badge);
}
On view Model I used raisedPropertyChanged()
Badge appears normally, just don't change value.
Tablayout
Out of the box there is nothing in mvvmcross to bind the content of a TabLayout when you provide a custom view. You could however try something custom using MvxFrameControl
Basically, replace your LinearLayout by the MvxFrameControl, then after
tabLayout.SetupWithViewPager(viewPager);
inflate your custom view using the BindingInflate method, and set a value to your MvxFrameControl's BindingContext, then set your custom tablayout view with the result that operation.
That might do the trick.
Another way to do it, is to listen to your ViewModel's "PropertyChanged" events in your Activity, and manually make changes to your tab layouts when it applies.
So I'm a bit of a newb in Android. I've read a few tutorials but found it extensively complicated to understand. I was hoping someone can help me understand on how to implement Animations to views on the current context I'm working on (noob friendly).
Let's say this is my .axml file:
<?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:id="#+id/top_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical" />
Now this is my activity (Not exactly but enough information to know what I want to do:
private LinearLayout _topContainer;
private IDictionary<string, FrameLayout> _framelayoutViewsDictionary = new Dictionary<string, FrameLayout>();
private LinearLayout.LayoutParams layoutParams;
protected override void OnCreate(Bundle bundle)
{
//SetContentView and other stuff...
layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent, 1);
_topContainer = FindViewById<LinearLayout>(Resource.Id.top_container);
}
public void CreateFirstVideoPlayer
{
_framelayoutViewsDictionary.Add(Constants.Views.TOP_FRAMELAYOUT, new FrameLayout(this)
{
Id = 1,
LayoutParameters = layoutParams
});
var fragmentManager = FragmentManager.BeginTransaction();
fragmentManager.Add(_framelayoutViewsDictionary[Constants.Views.TOP_FRAMELAYOUT].Id, /*Create New MediaPlayer Here*/, Constants.FragmentTag.TOP_FRAGMENT);
fragmentManager.Commit();
_topContainer.AddView(_framelayoutViewsDictionary[Constants.Views.TOP_FRAMELAYOUT]);
}
public void CreateSecondVideoPlayer
{
_framelayoutViewsDictionary.Add(Constants.Views.BOTTOM_FRAMELAYOUT, new FrameLayout(this)
{
Id = 2,
LayoutParameters = layoutParams
});
var fragmentManager = FragmentManager.BeginTransaction();
fragmentManager.Add(_framelayoutViewsDictionary[Constants.Views.BOTTOM_FRAMELAYOUT].Id, /*Create New MediaPlayer Here*/, Constants.FragmentTag.BOTTOM_FRAGMENT);
fragmentManager.Commit();
_topContainer.AddView(_framelayoutViewsDictionary[Constants.Views.BOTTOM_FRAMELAYOUT]);
}
As you can see. I'm programmatically creating a new FrameLayout, adding a fragment on top. And then putting that FrameLayout on top view which is a LinearLayout. Now when I add the second FrameLayout. The first FrameLayout is halved and the second one is added. So now each FrameLayout is taking 50:50 space. So what I want to do is. When the second FrameLayout is added, I want the first FrameLayout to animate so it slowly moves upwards to the top half of the screen instead of instantly appearing on the top. And when I remove the second FrameLayout the first FrameLayout will slowly animate back to the centre of the screen.
Hope this all makes sense. If you need more info please comment!
Using the Support Libraries to perform a fragment slide in/out is as easy as setting the Fragment's custom animations to the built-in resource abc_slide_in_bottom and abc_slide_out_bottom animations.
Example:
SupportFragmentManager
.BeginTransaction()
.SetCustomAnimations(
Resource.Animation.abc_slide_in_bottom,
Resource.Animation.abc_slide_out_bottom,
Resource.Animation.abc_slide_in_bottom,
Resource.Animation.abc_slide_out_bottom)
.AddToBackStack(count.ToString())
.Add(Resource.Id.linearLayout1, new AFragmentSubClass(), count.ToString())
.Commit();
I can't get an image to load into an ImageViewAsync. There's just a blank where the image should be. I've tried both synchronous and asychronous approaches.
I have the image placeholderProfileImage.png in the mipmap folders. I walked the debugger through the binding code and all appears to be in order. Note that I removed other code that populates the view with text. That part is working. What am I doing wrong with respect to the image?
profilePhotoImageView is defined in a layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/acquaintanceRow"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center">
<FFImageLoading.Views.ImageViewAsync
android:id="#+id/profilePhotoImageView"
android:scaleType="fitCenter"
android:layout_width="50dp"
android:layout_height="100dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:transitionName="#string/profilePhotoTransition" />
>
The view holder class contains ProfilePhotoImageView:
internal class MyViewHolder : RecyclerView.ViewHolder
{
// removed stuff for brevity
public ImageViewAsync ProfilePhotoImageView { get; }
public MyViewHolder(View itemView) : base(itemView)
{
MyRow = itemView;
// removed stuff for brevity
ProfilePhotoImageView = MyRow.FindViewById<ImageViewAsync>(Resource.Id.profilePhotoImageView);
}
}
Binding code:
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
var viewHolder = holder as MyViewHolder;
string photoUrl = "placeholderProfileImage.png:";
FFImageLoading.Work.TaskParameter taskParameter = ImageService.LoadFileFromApplicationBundle(photoUrl);
FFImageLoading.Work.TaskParameter taskParameter2 = taskParameter.Transform(new CircleTransformation());
taskParameter2.Into(viewHolder.ProfilePhotoImageView);
// tried asynchronous as well, nothing
//FFImageLoading.Work.TaskParameter taskParameter = ImageService.LoadUrl(photoUrl);
//FFImageLoading.Work.TaskParameter taskParameter2 = taskParameter.Transform(new CircleTransformation());
//taskParameter2.Into(viewHolder.ProfilePhotoImageView);
}
LoadFileFromApplicationBundle is loading the file from Assets not the mipmap folder. So you have to move the file to your Assets folder and set the build action to AndroidAsset.
All,
I've got a ViewGroup subclass which overrides OnCreateDrawableState() (Xamarin.Android is in C# so forgive the Pascal Casing).
My override of OnCreateDrawableState() never gets called, however. I've tried calling RefreshDrawableState(), DrawableStateChanged(). RequestLayout(), and Invalidate().
Nothing seems to work. This is the method:
/// <summary>
/// Handles the create drawable state event by adding in additional states as needed.
/// </summary>
/// <param name="extraSpace">Extra space.</param>
protected override int[] OnCreateDrawableState (int extraSpace)
{
int[] drawableState = base.OnCreateDrawableState(extraSpace + 3);
if (Completed)
{
int[] completedState = new int[] { Resource.Attribute.completed };
MergeDrawableStates(drawableState, completedState);
}
if (Required)
{
int[] requiredState = new int[] { Resource.Attribute.required };
MergeDrawableStates(drawableState, requiredState);
}
if (Valid)
{
int[] validState = new int[] { Resource.Attribute.valid };
MergeDrawableStates(drawableState, validState);
}
Android.Util.Log.Debug("ROW_VIEW", "OnCreateDrawableState Called");
return drawableState;
}
I assume it'll work OK - but it just never gets called. The ViewGroup itself is nested in a ListView and/or a LinearLayout but nothing seems to help.
This related question has no answers that work for me.
Edit: (I edited my previous answer incorrect answer where assumed you were implementing the Checkable interface)
OnCreateDrawableState seems to be propagated from the leaf nodes up to it's parent nodes (ViewGroups) only if a child element (leaf) declares android:duplicateParentState for instance in a Textview. As I understand it RefreshDrawableState goes down to the leaves and OnCreateDrawableState up from the leaves if android:duplicateParentState="true" is set, I haven't done a thorough analysis though, would be interested in any good pointers to documentation.
The following layout as an item in a ListView will cause onCreateDrawableState on MyLinearLayout to be called:
<com.example.android.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...>
<TextView
...
android:duplicateParentState="true"/>
</com.example.android.MyLinearLayout>
This won't:
<com.example.android.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...>
<TextView
...
android:duplicateParentState="false"/>
</com.example.android.MyLinearLayout>
Neither will this (The LinearLayout won't propagate up):
<com.example.android.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...>
<LinearLayout
...
android:duplicateParentState="false">
<TextView
...
android:duplicateParentState="true"/>
</LinearLayout>
</com.example.android.MyLinearLayout>
This again will:
<com.example.android.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...>
<LinearLayout
...
android:duplicateParentState="true">
<TextView
...
android:duplicateParentState="true"/>
</LinearLayout>
</com.example.android.MyLinearLayout>
Note that there seems to be some amalgam with the implementation of the Checkable interface.
The Checkable interface can be implemented by the Views that are immediate children in a ListView, GridView etc. There is no need to have it implemented further down the view tree.
In this case the ListView when in choice mode will call setChecked on the Checkable interface:
http://androidxref.com/4.3_r2.1/xref/frameworks/base/core/java/android/widget/ListView.java#1899
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
if (child instanceof Checkable) {
((Checkable) child).setChecked(mCheckStates.get(position));
}
The implementation of the Checkable usually adds a drawable state by overriding OnCreateDrawableState. See my other post for an example of this:
MvxListView checkable list item