I am creating a xamarin forms app and i want to change the transition when navigating between pages. I couldnt use https://components.xamarin.com/view/customnavpage because im using ContentPage. I also read the famous thread on xamarin forums but nothing worked for me. here is the link.
https://forums.xamarin.com/discussion/18818/custom-page-transitions-with-xamarin-forms
i'm using xamarin forms 2.3.4.247 and android api level 25 and appCompat 23.3.0.
any idea?
I found a workaround and I answer my own question maybe it helps someone else.
First we need to create a custom renderer for any platform(in this case android)
. create a new class under your Renderers folder in Droid target.
CustomTransitionsRenderer.cs
[assembly:ExportRenderer(typeof(NavigationPage),typeof(CustomTransitionsRenderer))]
namespace TesarSmartwatchForms.Droid.Renderers
{
public class CustomTransitionsRenderer : Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer
{
//SwitchContentAsync
protected override void SetupPageTransition(Android.Support.V4.App.FragmentTransaction transaction, bool isPush)
{
if (isPush)
transaction.SetCustomAnimations(Resource.Animator.move_in_left, 0);
else //prevView enter:
transaction.SetCustomAnimations(Resource.Animator.side_in_right, 0);
}
}
}
and then add your custom animations under Droid>Resources>animator like these:
move_in_left.xml
<?xml version="1.0" encoding="UTF-8" ?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_interpolator">
<translate
android:fromXDelta="-100%p"
android:toXDelta="0"
android:duration="300"/>
</set>
and slide_in_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<translate
android:fromXDelta="100%p"
android:toXDelta="0"
android:duration="300" />
</set>
then we need to modify our android theme just adding this line
<item name="android:windowBackground">#android:color/transparent</item>
and remember to navigate between pages with the default navigation transition, just like this
Navigation.PushAsync(page);
Related
I am a beginner in Xamarin. Now I want to add a ResourceDictionary for making a Theme.
In https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.resourcedictionary?view=xamarin-forms:
The Namespace of ResourceDictionary is Xamarin.Forms.
Whereas, there is not any ResourceDictionary template.
I tried to search it again:
There is nothing about this. I am using the Visual Studio Community 2019 Version 16.5.4. Why it turns out to be this and how can I solve it?
Thank you.
I think that you are mixing the terms here. Namespaces and assemblies are totally different things than the New item templates inside Visual studio. ResourceDictionary class is inside the Xamarin.Forms, indeed, and in the same time inside the Xamarin.Forms.Core.dll. This doesn't mean that it should be inside the new item template. There are a lot of other classes inside this namespace.
Having said that, you can create ResourceDictionary class in 2 ways:
If you want to write in it entirely in c#, what you will need is a .cs file. The file can be either ContentPage (C#) from the templates above (the second item from your screenshot), or a simple .cs calss file will do the work also. After that, inherit from ResourceDictionary class like so:
public class MyResourceDictionary : Xamarin.Forms.ResourceDictionary
{
}
If you want to write in it in xaml, then simply create a new ContentPage (the first item from your screenshot). Any other type of the combo .xaml together with a .xaml.cs code-behind file will work too. After the files have been created, change their structure from:
MyResoruceDictionary.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LEUA.Services.MyResourceDictionary">
<ContentPage.Content>
<StackLayout>
<Label Text="Hello, world!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
MyResourceDictionary.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MyResourceDictionary : ContentPage
{
public MyResourceDictionary()
{
InitializeComponent();
}
}
to this
MyResoruceDictionary.xaml
<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LEUA.Services.MyResourceDictionary">
</ResourceDictionary>
MyResourceDictionary.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MyResourceDictionary : Xamarin.Forms.ResourceDictionary
{
public MyResourceDictionary()
{
InitializeComponent();
}
}
Issue: When using a Navigation Drawer Activity, Picasso loads images during emulation, but not during USB debugging... Any help is greatly appreciated!
UPDATE: SOLUTION In Answer!
Here's an image of my phone not showing the image, and the emulator working fine. I'm using a YouTube thumbnail as an online test image:
https://imagizer.imageshack.com/img921/7876/4sd4ak.jpg
I noticed this in a larger project I was working on when I decided to whip it out on my phone, but in searching for the solution was able to isolate it to a fresh Navigation Drawer Layout Activity.
Here's what I know:
All my SDK, AndroidStudio, GooglePixel 3XL Phone (IRL), are updated
Invalidated/Restarted my Cashes in Android Studio
The issue also occurs when migrated to AnrdroidX
All Android phones work as expected when using the emulator, just not the USB Debugging on my physical Google Pixel 3XL
UPDATE: I got it to work on my Samsung Galaxy 7 through USB!
Other layouts like Empty Activity/etc all work fine, even in the same project
I made a new Navigation Drawer Layout Activity in Android Studio and added this:
1) Build.gradle (Module:app) dependencies:
implementation 'com.squareup.picasso:picasso:2.5.2'
2) In my Android Manifest: uses-permission android:name="android.permission.INTERNET"
3) An ImageView to my content_main
4) In my MainActivity's onCreate:
Picasso.with(this).load("http://img.youtube.com/vi/ek-5vIz_gDw/0.jpg").into(imageView)
// MainActivity without the additional override functions (no changes)
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val fab: FloatingActionButton = findViewById(R.id.fab)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val toggle = ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener(this)
Picasso.with(this).load("http://img.youtube.com/vi/ek-5vIz_gDw/0.jpg").into(imageView)
}
And my content_main.xml
<?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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main"
tools:context=".MainActivity">
<ImageView
android:layout_width="0dp"
android:layout_height="0dp" app:srcCompat="#mipmap/ic_launcher_round"
android:id="#+id/imageView" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:contentDescription="#string/description"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I'm not getting any error messages on run, only the image just doesn't load in USB Debugging IRL.
UPDATE: So I was able to get it working on all other physical phones I tried it on. However To get it to work on the Google Pixel 3XL, I had to make this change. Not sure why it is any different, but it does work!
I was doing this before (Did not work only my physical Pixel 3):
val imageLink = video.link
Picasso.with(context).load("http://img.youtube.com/vi/$imageLink/0.jpg").into(imageView)
Not sure why, but here's the solution that works:
val imageLink = "https://img.youtube.com/vi/${video.link}/0.jpg"
Picasso.with(context).load(imageLink).into(imageView)
Hope this helps anyone in the same predicament!
I'm trying to display and embedded image in a shared project resource (as explained here on microsoft documentation).
I created the ImageResourceExtension, the project compiles, but I get the following error when I start the project :
Could not load type 'Xamarin.Forms.Xaml.IReferenceProvider' from
assembly 'Xamarin.Forms.Core, Version=2.0.0.0
Here's my code :
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App1"
x:Class="App1.MainPage">
<StackLayout>
<Image x:Name="imgTest" Source="{local:ImageResource img.jpg}" />
</StackLayout>
</ContentPage>
EmbeddedImage.cs
namespace App1
{
[ContentProperty(nameof(Source))]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
return null;
// Do your translation lookup here, using whatever method you require
var imageSource = ImageSource.FromResource(Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
return imageSource;
}
}
}
You can try this, it works for me
xyz.xaml.cs
imgName.Source = ImageSource.FromResource("ProjectName.Images.backicon.png");
xyz.xaml
<Image x:Name="imgName" />
Hope this code helps you!!
Not knowing if the answer is still valid for you, but I usually have an Assets folder outside my solution which contains Android specific folders (drawables), iOS specific folders (Resource with #2x and #3x) and a Common folder for shared images.
In my solution I add these files as a link in the folders they should be associated with. On Android in the Resources/Drawable and iOS in the Resource. In this case Common files can be shared across both platforms without physically copying them.
As a bonus, updates to these Assets can be overwritten in the folder outside my solution and will be used within my solution without any additional action to be taken.
Replace:
<Image x:Name="imgTest" Source="{local:ImageResource img.jpg}" />
With:
<Image x:Name="imgTest" Source="{local:ImageResource 'Project.Folder.img.jpg'}" />
And Replace:
var imageSource = ImageSource.FromResource(Source, typeof(...));
With:
var imageSource = ImageSource.FromResource(Source);
If you add the Image to your Android drawable folder, or to the iOS Resource folder, you don't need any extension. You can simply do:
<Image x:Name="imgTest" Source="img.jpg" />
I'm trying to get a "simple" UI done, but I'm stuck at where I want to put icons in my bottom tabs. So far I got the following code:
`public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTabHost mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), android.R.id.tabcontent);
mTabHost.addTab(
mTabHost.newTabSpec("tab1").setIndicator("AddStuff", getResources().getDrawable(R.drawable.ic_add_white_24dp)),
FragmentTabAdd.class, null);
mTabHost.addTab(
mTabHost.newTabSpec("tab2").setIndicator("Favorites", getResources().getDrawable(R.drawable.ic_add_white_24dp)),
FragmentTabSelectFavorites.class, null);
mTabHost.addTab(
mTabHost.newTabSpec("tab3").setIndicator("Messages", getResources().getDrawable(R.drawable.ic_add_white_24dp)),
FragmentTabMessages.class, null);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}`
and I got the following as my .xml for each tab:
<?xml version="1.0" encoding="utf-8"?>
<selector android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<!-- When selected, use black -->
<item android:drawable="#drawable/ic_add_black_24dp"
android:state_selected="true" />
<!-- When not selected, use white-->
<item android:drawable="#drawable/ic_add_white_24dp" />
</selector>
I worked through several different tutorials, but none had an Actionbar and a Tabbar with icons. I'm happy for any tipps and suggestions.
Thank you in advance!
I found the answer myself after several hours of trying different things.
The way to add Icons to the bottom tab bar is to insert "null" here:
mTabHost.addTab(
mTabHost.newTabSpec("tab1").setIndicator("AddStuff", getResources().getDrawable(R.drawable.ic_add_white_24dp)),
FragmentTabAdd.class, null);
null has to be written where "AddStuff" is now.
I even colored the background with an image:
mTabHost.setBackground(getResources().getDrawable(R.drawable.tab_background));
Maybe this will help someone else save some time :)
I am trying adopt the v21 AppCompat libraries and leverage the better control of the ActionBar using a Toolbar as described here and here. But no matter how I modify the menu XML, I can only get the menu items to show up in the overflow area. I would like to see the MenuItem represented as an icon on the Toolbar/ActionBar.
My menu declaration looks like this (note the showAsAction line):
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:res-auto="http:/>/schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity" >
<item android:id="#+id/action_add"
android:icon="#android:drawable/ic_menu_add"
android:title="#string/action_add"
android:orderInCategory="2"
res-auto:showAsAction="always" />
</menu>
I have also tried this (with a slightly different showAsAction line):
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:res-auto="http:/>/schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity" >
<item android:id="#+id/action_add"
android:icon="#android:drawable/ic_menu_add"
android:title="#string/action_add"
android:orderInCategory="2"
android:showAsAction="always" />
</menu>
But the only way I have successfully been able to get the icon to show up on the Toolbar/ActionBar is to force it in code.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
// Try to manually force the item onto the bar instead of allowing it in the overflow
// for some reason, android is not picking up the setting in the menu declaration
// using android:showAsAction="always" (even when using the auto-res namespace)
MenuItem addItem = menu.findItem(R.id.action_add);
MenuCompat.setShowAsAction(addItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
return true;
}
I am using the android.support.v4.view.MenuCompat static methods to achieve this. But I believe I should be able to do this declaratively in the XML. I have tried using both "always" and "ifRoom" but for no effect. I can only assume that the XML attribute is not being picked up.
I guess it is really something simple or related to the fact that I am using the new Toolbar to function as the holder of the menu. The Toolbar layout is very simple:
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
and the usage seems quite standard:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Any help would be appreciated. And I am happy to share more of the project content if it helps to get to the bottom of it.