How to make 2 layouts sliding on button click in xamarin/android? - xamarin.android

I'm begining with xamarin and android, and I'm not sure to understand the good way to do.
Then I created a main activity and a second activity with their respective layouts.
In the first I put a button with that code:
button.Click += (sender, e) =>
{
var intent = new Android.Content.Intent(this, typeof(Activity1));
StartActivity(intent);
OverridePendingTransition(Android.Resource.Animation.SlideInleft, Android.Resource.Animation.SlideInleft);
};
And in the second:
button.Click += (sender, e) =>
{
Finish();
};
But this doesn't do what I want, I would like the two layouts two slide as if there were side by side, but here the second layout just slides on the first. Also it comes from the left were I would like it to come from the right and there's no SlideInright.
Also is it the right way to do using two activities, mustn't I have only one activity and two layouts (views?).

First, you could use one activity which contains two ViewGroup. As for your question, you can use Animation and FrameLayout which contains two RelativeLayout to complete what you want, like this:
MainActivity.axml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:a="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rl2"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#android:color/holo_green_dark">
<Button
android:id="#+id/bt2"
android:text="page2"
android:layout_height="100dp"
android:layout_width="100dp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/rl1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#android:color/holo_red_dark">
<Button
android:id="#+id/bt1"
android:text="page1"
android:layout_height="100dp"
android:layout_width="100dp" />
</RelativeLayout>
</FrameLayout>
MainActivity:
[Activity(Label = "Aniamtion", MainLauncher = true)]
public class MainActivity : Activity
{
Button bt1,bt2;
RelativeLayout rl1, rl2;
int width;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
getScreenWidth();//get the screen's width, so we can define how much the animation can translate
initView();
initListener();
}
private void getScreenWidth()
{
DisplayMetrics dm = new DisplayMetrics();
WindowManager.DefaultDisplay.GetMetrics(dm);
width = dm.WidthPixels;
}
private void initListener()
{
bt1.Click += toPage1;
bt2.Click += toPage2;
}
private void toPage1(object sender, EventArgs e)
{
//use ObjectAnimator to complete it
ObjectAnimator objectAnimator = ObjectAnimator.OfFloat(rl1, "translationX", 0, -width);
objectAnimator.SetDuration(500);
objectAnimator.Start();
ObjectAnimator objectAnimator1 = ObjectAnimator.OfFloat(rl2, "translationX", width, 0);
objectAnimator1.SetDuration(500);
objectAnimator1.Start();
}
private void toPage2(object sender, EventArgs e)
{
ObjectAnimator objectAnimator = ObjectAnimator.OfFloat(rl1, "translationX", -width, 0);
objectAnimator.SetDuration(500);
objectAnimator.Start();
ObjectAnimator objectAnimator1 = ObjectAnimator.OfFloat(rl2, "translationX", 0, width);
objectAnimator1.SetDuration(500);
objectAnimator1.Start();
}
private void initView()
{
bt1 = FindViewById<Button>(Resource.Id.bt1);
bt2 = FindViewById<Button>(Resource.Id.bt2);
rl1 = FindViewById<RelativeLayout>(Resource.Id.rl1);
rl2 = FindViewById<RelativeLayout>(Resource.Id.rl2);
}
}
Second, about this OverridePendingTransition(Android.Resource.Animation.SlideInleft, Android.Resource.Animation.SlideInleft) method, the parameter you can use System resource, or you can custom it .
Update:
put this into your Resource->anim->SlideInRight, this is about customing animation in Xamarin.Android, it is same as Android, and this is document which you can refer to
<?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="50%p"
android:toXDelta="0"
android:duration="300"/>
</set>

Related

Xamarin.Forms SkiaSharp Gradient working on Android but not on iOS

We need a Gradient on our pages, so we're using SkiaSharp and a GradientView. This works fine on Android but isn't working on iOS - the Gradient just doesn't display.
Do we need to do any iOS-specific initialisation for SkiaSharp on iOS, with renderers or code in the AppDelegate?
Edit This is running on an iPad with iOS 10.3.3.
Our XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyProject.XForms.Controls.GradientView">
</ContentView>
Our XAML.cs
using SkiaSharp;
using SkiaSharp.Views.Forms;
using Xamarin.Forms;
namespace MyProject.XForms.Controls
{
public partial class GradientView : ContentView
{
public Color StartColor { get; set; } = Color.Transparent;
public Color EndColor { get; set; } = Color.Transparent;
public bool Horizontal { get; set; } = false;
public GradientView()
{
InitializeComponent();
SKCanvasView canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
var colors = new SKColor[] { StartColor.ToSKColor(), EndColor.ToSKColor() };
SKPoint startPoint = new SKPoint(0, 0);
SKPoint endPoint = Horizontal ? new SKPoint(info.Width, 0) : new SKPoint(0, info.Height);
var shader = SKShader.CreateLinearGradient(startPoint, endPoint, colors, null, SKShaderTileMode.Clamp);
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Fill,
Shader = shader
};
canvas.DrawRect(new SKRect(0, 0, info.Width, info.Height), paint);
}
}
}
I ran into the same problem and read the documentation. It says you need to tell the canvas to update. You do this using the following line of code:
canvasView.InvalidateSurface();
Maybe you haven't installed the NuGets (both SkiaSharp and SkiaSharp.Views.Forms) into the iOS project?
I copy-pasted your code into a brand new app, and it worked first time.
Some other things that may be the issue is that the view height/width is 0. Or, the dodgy case where the color is transparent.

Android onDraw doesn't draw anything in custom EditText

similar problems
I have a Custom EditText:
public class MyEditText extends AppCompatEditText {
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
canvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2, getPaint());
}
}
in xml:
<com.angcyo.myapplication.MyEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
Normal effect:
effect
But If you Simultaneous setting
android:gravity="right" android:inputType="text"
like this:
<com.angcyo.myapplication.MyEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:gravity="right"
android:inputType="text"/>
Well, the result is...
result
What happened? doesn't draw anything?
Try to extend EditText rather than AppCompatEditText.
And change getmeasuredHeight() and getmeasuredWidth() to getHeight() and getWidth() then see.
Initialize Paint like
Paint paint =new Paint(); paint.setColor(Color.BLACK);
and change the radius to 50f or 60f in third parameter and then see.

Spinner onItemSelected to clear the EditText Text

I have a spinner on one of my Activity that on initialization will load the data from database for spinner.setSelection(0). When I change the spinner value, lets say spinner.setSelection(1), I want to clear the text from EdittText ed1 View prior to loading the data(if exist) or leave it blank/null/empty
Here is the snippet of my code.
public class TestActivity extends Activity implements
AdapterView.OnItemSelectedListener {
...
Spinner spinner;
EditText ed1;
...
protected void onCreate(Bundle savedInstanceState) {
...
...
spinner = (Spinner) findViewById(R.id.spinner1);
ed1 = (EditText)findViewById(R.id.ed1);
...
adapter = new ArrayAdapter<String>(this,R.layout.temp_layout01,R.id.temptxt01,xNames);
spinner.setAdapter(adapter);
spinner.setSelection(getSpinnerIndex(spinner,mname));
spinner.setOnItemSelectedListener(this);
}
Method to clear the EditText data
private void clearAllFields() {
Log.i(TAG, "Clearing Fields");
ed1.getText().clear(); //test that didn't clear the data
ed1.setText(null); // test that didn't clear the data
}
onItemSelected for spinner listener
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
clearAllFields();
mname = parent.getItemAtPosition(position).toString();
mID = dbHelper.getCurrentData(mname);
spinner.setSelection(getSpinnerIndex(spinner,mname));
populateData();
}
The ed1 is within a TableRow
<TableRow
android:id="#+id/tbHole18TR"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<EditText
android:layout_width="50dp"
android:layout_height="wrap_content"
android:inputType="number"
android:ems="10"
android:id="#+id/ed1"
android:background="#color/Green3"
android:textAlignment="center" />
</TableRow>
Is this something to do with focusChange etc.
Try this logic
get current spinner data and EditText data
compare them if find not equal clear else do nothing

Why is my WPF binding not working in state change?

I have some items in a WrapPanel. I want to be able to click on an item and have it expand to the full width of the wrap panel. I tried doing this by creating two states, Expanded and Colapsed, in the control that is used for each item. For the Expanded state, I bound the Width of the control to be equal to the ActualWidth of the WrapPanel.
When I didn't get the result I expected, I tried setting Expanded value to a specific number (instead of the the binding). That is working. The items toggle between the two Colapsed and Exapanded widths. I still want to have the Expanded state be equal to the width of the WrapPanel though, not an arbitrary fixed width. I know my binding works because if I just bind the Width property directly (not via visual states), the items in the WrapPanel match its width.
Expanded state with Binding - Doesn't work:
<VisualState x:Name="Expanded">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="JobMaster">
<EasingDoubleKeyFrame KeyTime="0">
<EasingDoubleKeyFrame.Value>
<Binding
Path="ActualWidth"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type WrapPanel}}" />
</EasingDoubleKeyFrame.Value>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Expanded State with hard coded value - Works
<VisualState x:Name="Expanded">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="JobMaster">
<EasingDoubleKeyFrame KeyTime="0" Value="800" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Bind the control Width property directly works
<UserControl.Width>
<Binding
Path="ActualWidth"
RelativeSource="{RelativeSource AncestorType={x:Type WrapPanel}}" />
</UserControl.Width>
So why doesn't the Binding in the state work or is there another way to do this?
I was never able to get this working using visual states. Instead I wrote a behavoir.
public class TileExpandColapseBehavoir : Behavior<Control>
{
private ITile _data;
#region Properties
public static readonly DependencyProperty TileControlProperty = DependencyProperty.Register("TileControl", typeof(object), typeof(TileExpandColapseBehavoir), new PropertyMetadata(null));
public static readonly DependencyProperty DefaultWidthProperty = DependencyProperty.Register("DefaultWidth", typeof(Double), typeof(TileExpandColapseBehavoir), new PropertyMetadata(null));
public object TileControl
{
get { return (object)this.GetValue(TileControlProperty); }
set { this.SetValue(TileControlProperty, value); }
}
public double DefaultWidth
{
get { return (double)this.GetValue(DefaultWidthProperty); }
set { this.SetValue(DefaultWidthProperty, value); }
}
#endregion
public TileExpandColapseBehavoir()
{
}
protected override void OnAttached()
{
this.AssociatedObject.PreviewMouseDown +=new MouseButtonEventHandler(AssociatedObject_MouseUp);
}
private void AssociatedObject_MouseUp(object sender, MouseButtonEventArgs e)
{
UIElement child = (UIElement)sender;
WrapPanel parentWrap = FindAncestorUtil.TryFindAcestor<WrapPanel>(child);
if (parentWrap != null && TileControl is UserControl)
{
GetData();
if (_data.IsExpanded == false)
{
Binding newBinding = new Binding();
newBinding.Source = parentWrap;
newBinding.Path = new PropertyPath("ActualWidth");
UserControl thisTile = (UserControl)TileControl;
BindingOperations.SetBinding(thisTile, UserControl.WidthProperty, newBinding);
_data.IsExpanded = true;
}
else
{
UserControl thisTile = (UserControl)TileControl;
BindingOperations.ClearBinding(thisTile, UserControl.WidthProperty);
thisTile.Width = DefaultWidth;
_data.IsExpanded = false;
}
}
}
private void GetData()
{
if (_data == null && AssociatedObject.DataContext is ITile)
{
_data = (ITile)AssociatedObject.DataContext;
}
}
}
Your RelativeSource binding is looking for an ancestor of the animation, not the target of the animation. Try giving your WrapPanel a name and use Element binding instead.
<Binding Path="ActualWidth" ElementName="MyWrapPanel"/>

I Want to display a listview when i click a button in Monodroid. i tried this coding. its not running. Can anyone correct this

I want to display a listview when I click a button in Monodroid. I tried the following code, however it doesn't run. Can anyone correct this?
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView (Resource.Layout.Main);
Button button1 = FindViewById<Button> (Resource.Id.btn);
button1.Click += delegate { listviewFunction(); };
}
public void listviewFunction()
{
ListAdapter = new ArrayAdapter<string>(this, Resource.Layout.list_item, _countries);
ListView.TextFilterEnabled = true;
ListView.ItemClick += (sender, args) => Toast.MakeText(Application, ((TextView) args.View).Text, ToastLength.Short).Show();
}
Try just:
button1.Click += ...
Declare a ListView globally:
private ListView _listView;
Now (1)create the ListView, OR (2)get it from a axml file:
(1)
_listView = new ListView(this);
(2)
_listView = (ListView)View.FindViewById(Resource.Id.MyList);
Now create your adapter, then:
_listView.SetAdapter(myAdapter);
Then create your ItemClick handler:
_listView.ItemClick += (sender, args) => Toast.MakeText(Application, ((TextView) args.View).Text, ToastLength.Short).Show();

Resources