after I thought that I finally finished my android app, I discovered that when my phone screen rotates, my application crashes. so after doing some research, I figured out that I have to add this line to my activities:
[Activity(Label = "FreeLineApp", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true, NoHistory = true, ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
this worked, but not completely. In fact, my app has a login fragment that appears once I launch the app. this fragment is displayed within a login activity that is set to be the main launcher with an empty layout. this login fragment doesn't appear totally when the phone screen is rotated. like it is cropped.
here is my login xml of the fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:gravity="center"
android:minHeight="1500px"
android:minWidth="1000px"
>
<TextView
android:text="Welcome to FreeLineApp!"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView1"
android:layout_marginBottom="40dp"
android:textAlignment="center"
android:textColor="#android:color/holo_blue_dark"/>
<EditText
android:layout_width="match_parent"
android:hint="Account"
android:id="#+id/editText1"
android:background="#drawable/logincustom"
android:layout_height="200px"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"/>
<EditText
android:layout_width="match_parent"
android:hint="Password"
android:id="#+id/editText2"
android:layout_marginTop="20dp"
android:layout_height="200px"
android:background="#drawable/logincustom"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"/>
<Button
android:layout_width="400px"
android:layout_height="wrap_content"
android:id="#+id/button1"
android:text="Login"
android:layout_marginTop="30dp"
android:background="#drawable/buttoncustom"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/checkBox1"/>
<TextView
android:text="Keep me logged in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView2"
android:layout_toRightOf="#+id/checkBox1"
android:layout_marginRight="20dp"
android:textColor="#android:color/holo_blue_dark"
android:layout_marginTop="6dp"
/>
</RelativeLayout>
</LinearLayout>
and here is my login activity where the fragment appears:
[Activity(Label = "FreeLineApp", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true, NoHistory = true, ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
public class LoginActivity : AppCompatActivity,OnLoginInforCompleted
{
private AlertDialog _dialog;
ISharedPreferences pref = Application.Context.GetSharedPreferences("UserInfo", FileCreationMode.Private);
public void inputLoginInforCompleted(string userName, string passWord)
{
appuser app_user = new appuser()
{
UserName = user.Username,
Password = user.Password
};
Intent intent = new Intent(this, typeof(MainActivity));
intent.PutExtra("User", JsonConvert.SerializeObject(app_user));
this.StartActivity(intent);
//throw new NotImplementedException();
StartActivity(new Intent(this, typeof(MainActivity)));
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.layout1);
// StartActivity(typeof(MainActivity));
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)
{
string userName = pref.GetString("Username", String.Empty);
string password = pref.GetString("Password", String.Empty);
if (userName == String.Empty || password == String.Empty)
{
MyDialogFragment dialogFragment = new MyDialogFragment();
dialogFragment.setOnLoginInforCompleted(this);
dialogFragment.Cancelable = false;
var SupportFragmentManager = this.FragmentManager;
dialogFragment.Show(SupportFragmentManager, "dialog");
}
else
{
Intent intent = new Intent(this, typeof(MainActivity));
appuser app_user = new appuser()
{
UserName = user.Username,
Password = user.Password
};
intent.PutExtra("User", JsonConvert.SerializeObject(app_user));
this.StartActivity(intent);
}
}
else
{
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.SetTitle("Connection failed");
alert.SetMessage("Please, check your internet Connection!");
alert.SetNeutralButton("okay", (senderAlert, args) => {
alert.Dispose();
MyDialogFragment dialogFragment = new MyDialogFragment();
dialogFragment.setOnLoginInforCompleted(this);
dialogFragment.Cancelable = false;
var SupportFragmentManager = this.FragmentManager;
dialogFragment.Show(SupportFragmentManager, "dialog");
});
_dialog = alert.Create();
_dialog.Show();
}
// Create your application here
}
}
}
in the following images is what happens when the phone screen is rotated:
what should i do?
You can create two layouts ,one is used for Portrait, and other is used for Landscape. Then when screen is rotated, it will show as your wants.
For example , the Layout folder is as follow:
And remove ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize from Activity.
Then the layout will changes when the phone screen is rotated.
Related
i need to display a video in mobile app which was developed in Xamarin(Andriod) in which the for forward it moving 15 sec ahead and for backward it is moving 5 sec back
Can i get some help on this
In your case you seems to use the MediaController . However , if you want to custom the length of forward and back , you need to create a custom MediaController .
in 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"
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/activity_main"
android:orientation="vertical">
<VideoView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/videoView1" />
<LinearLayout
android:background="#android:color/darker_gray"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:text="back"
android:id="#+id/back"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<Button
android:text="play"
android:id="#+id/play"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<Button
android:text="forward"
android:id="#+id/forward"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</LinearLayout>
</LinearLayout>
in Activity
VideoView videoView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_main);
//...
videoView = FindViewById<VideoView>(Resource.Id.videoView1);
videoView.SetVideoURI(Android.Net.Uri.Parse("xxx.mp4")); // Path of your saved video file.
videoView.Start();
Button back = FindViewById<Button>(Resource.Id.back);
back.Click += Back_Click;
Button play = FindViewById<Button>(Resource.Id.play);
play.Click += Play_Click;
Button forward = FindViewById<Button>(Resource.Id.forward);
forward.Click += Forward_Click; ;
}
private void Forward_Click(object sender, EventArgs e)
{
videoView.SeekTo(videoView.CurrentPosition + 5 * 1000);
}
private void Play_Click(object sender, EventArgs e)
{
var button = sender as Button;
if (videoView.IsPlaying)
{
button.Text = "Play";
videoView.Pause();
}
else
{
button.Text = "Pause";
videoView.Start();
}
}
private void Back_Click(object sender, EventArgs e)
{
videoView.SeekTo(videoView.CurrentPosition-15*1000);
}
And in this way you just need to set the icon of the Buttons as you want .
i am using xamarin android app template with drawerlayout.i am using webview in app_bar_main.axml. when the activity is launched .it overlaps the appbar and does not show toolbar.my app_bar_main.axml is as follows: i want to show webview but below appbar.the webview is below toolbar but contents of toolbar are hidden.i want contents of toolbar so that i can navigate through toolbar in appbar .app_bar_main.axml .
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/appBarLayout"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<ProgressBar
android:id="#+id/progressBar"
android:layout_below="#id/toolbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.widget.NestedScrollView
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:layout_gravity="fill_vertical"
android:layout_below="#id/progressBar"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<WebView
android:id="#+id/StoreView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
app:srcCompat="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
the MainActivity.cs code is here.
the app_bar_main.axml is in activity_main.axml as produced by drawerlayout template.
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;
DrawerLayout drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, Resource.String.navigation_drawer_open, Resource.String.navigation_drawer_close);
drawer.AddDrawerListener(toggle);
toggle.SyncState();
NavigationView navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
navigationView.SetNavigationItemSelectedListener(this);
// start store activity
if (IsOnline() == true)
{
message = "items";
var intent = new Intent(this, typeof(StoreActivity));
intent.PutExtra("Data", "message");
StartActivity(intent);
}
}
```
Here is a simple demo which achieve your function.The main code is as follows:
The activity_main.axml
<?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:orientation="vertical"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="#33B86C"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_width="match_parent">
<FrameLayout
android:background="#android:color/holo_purple"
android:id="#+id/content_frame"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_height="match_parent"
android:layout_width="200dp"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="#menu/menu" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
MainActivity.cs
public class MainActivity : AppCompatActivity
{
DrawerLayout drawer;
NavigationView navigationView;
private string mDrawerTitle;
private string[] mContentTitles;
Toolbar toolbar;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
mDrawerTitle = this.Title;
mContentTitles= this.Resources.GetStringArray(Resource.Array.contents_array);
toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetDisplayShowTitleEnabled(false);
SupportActionBar.SetHomeButtonEnabled(true);
SupportActionBar.SetHomeAsUpIndicator(Resource.Drawable.ic_menu);
// Get our button from the layout resource,
// and attach an event to it
drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
if (navigationView != null)
setupDrawerContent(navigationView);
ActionBarDrawerToggle toggle = new MyActionBarDrawerToggle(this, drawer, toolbar, Resource.String.drawer_open, Resource.String.drawer_close);
drawer.AddDrawerListener(toggle);
toggle.SyncState();
if (savedInstanceState == null) //first launch
{
toolbar.Title = mContentTitles[0];
var fragment = WebviewFragment.NewInstance(0);
var fragmentManager = this.FragmentManager;
var ft = fragmentManager.BeginTransaction();
ft.Replace(Resource.Id.content_frame, fragment);
ft.Commit();
}
}
void setupDrawerContent(NavigationView navigationView)
{
navigationView.NavigationItemSelected += (sender, e) => {
int ItemId = e.MenuItem.ItemId;
e.MenuItem.SetChecked(true);
int index = 0;
if (ItemId == Resource.Id.nav_home) {
index = 0;
} else if (ItemId == Resource.Id.nav_messages) {
index = 1;
}
else if (ItemId == Resource.Id.nav_about)
{
index = 2;
}
// update the main content by replacing fragments
var fragment = WebviewFragment.NewInstance(index);
var fragmentManager = this.FragmentManager;
var ft = fragmentManager.BeginTransaction();
ft.Replace(Resource.Id.content_frame, fragment);
ft.Commit();
// update selected item title, then close the drawer
mDrawerTitle = mContentTitles[index];
drawer.CloseDrawers();
};
}
internal class WebviewFragment : Fragment
{
public const string ARG_NUMBER = "planet_number";
public WebviewFragment()
{
// Empty constructor required for fragment subclasses
}
public static Fragment NewInstance(int position)
{
Fragment fragment = new WebviewFragment();
Bundle args = new Bundle();
args.PutInt(WebviewFragment.ARG_NUMBER, position);
fragment.Arguments = args;
return fragment;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View rootView = inflater.Inflate(Resource.Layout.fragment_content2, container, false);
var i = this.Arguments.GetInt(ARG_NUMBER);
var url = this.Resources.GetStringArray(Resource.Array.weburls_array)[i];
var title = this.Resources.GetStringArray(Resource.Array.contents_array)[i];
var web_view = rootView.FindViewById<WebView>(Resource.Id.webview);
web_view.Settings.JavaScriptEnabled = true;
web_view.SetWebViewClient(new HelloWebViewClient());
web_view.LoadUrl(url);
this.Activity.Title = title;
return rootView;
}
}
internal class MyActionBarDrawerToggle : ActionBarDrawerToggle
{
MainActivity owner;
public MyActionBarDrawerToggle(MainActivity activity, DrawerLayout layout, Toolbar toolbar, int openRes, int closeRes)
: base(activity, layout, toolbar, openRes, closeRes)
{
owner = activity;
}
public override void OnDrawerClosed(View drawerView)
{
owner.toolbar.Title = owner.Title;
owner.InvalidateOptionsMenu();
}
public override void OnDrawerOpened(View drawerView)
{
owner.toolbar.Title = owner.mDrawerTitle;
owner.InvalidateOptionsMenu();
}
}
}
strings.xml
<resources>
<string name="app_name">DrawLayoutApp</string>
<string name="action_settings">Settings</string>
<string name="drawer_open">Open navigation drawer</string>
<string name="drawer_close">Close navigation drawer</string>
<string-array name="contents_array">
<item>Home</item>
<item>Messages</item>
<item>About</item>
</string-array>
<string-array name="weburls_array">
<item>https://www.google.com/</item>
<item>https://msdn.itellyou.cn/</item>
<item>https://www.baidu.com/</item>
</string-array>
</resources>
menu.xml
<?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:title="Home" />
<item
android:id="#+id/nav_messages"
android:title="Messages" />
<item
android:id="#+id/nav_about"
android:title="About" />
</group>
</menu>
The effect is as follows:
This is the main activity where I am setting all the icons, menu, drawer and my navigation view. Here I set another view by inflating nav_header into the view and set the textview but I still can't seem to change the textview in the navigation drawer.
MainActivity
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Support.V4.Widget;
using Android.Views;
using RoutineApp.Fragments;
using Android.Support.V7.App;
using Android.Support.V4.View;
using Android.Support.Design.Widget;
using Android.Widget;
using Android.Content;
namespace RoutineApp
{
[Activity(Label = "#string/app_name", MainLauncher = true, LaunchMode = LaunchMode.SingleTop)]
public class MainActivity : AppCompatActivity
{
DrawerLayout drawerLayout;
NavigationView navigationView;
IMenuItem previousItem;
TextView UserNameTxt;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.main);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
if (toolbar != null)
{
SetSupportActionBar(toolbar);
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetHomeButtonEnabled(true);
}
drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
SupportActionBar.SetHomeAsUpIndicator(Resource.Drawable.ic_menu);
navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
LayoutInflater inflater = (LayoutInflater)GetSystemService(Context.LayoutInflaterService);
View view = inflater.Inflate(Resource.Layout.nav_header, null);
UserNameTxt = view.FindViewById<TextView>(Resource.Id.UserNameTxt);
UserNameTxt.Text = "Yousuf";
navigationView.NavigationItemSelected += (sender, e) =>
{
if (previousItem != null)
previousItem.SetChecked(false);
navigationView.SetCheckedItem(e.MenuItem.ItemId);
previousItem = e.MenuItem;
switch (e.MenuItem.ItemId)
{
case Resource.Id.nav_home_1:
ListItemClicked(0);
break;
case Resource.Id.nav_home_2:
ListItemClicked(1);
break;
}
drawerLayout.CloseDrawers();
};
if (savedInstanceState == null)
{
navigationView.SetCheckedItem(Resource.Id.nav_home_1);
ListItemClicked(0);
}
}
int oldPosition = -1;
private void ListItemClicked(int position)
{
if (position == oldPosition)
return;
oldPosition = position;
Fragment fragment = null;
switch (position)
{
case 0:
fragment = Fragment1.NewInstance();
break;
}
FragmentTransaction fragmentTx = this.FragmentManager.BeginTransaction();
fragmentTx.Replace(Resource.Id.content_frame, fragment);
fragmentTx.AddToBackStack(null);
fragmentTx.Commit();
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
switch (item.ItemId)
{
case Android.Resource.Id.Home:
drawerLayout.OpenDrawer(GravityCompat.Start);
return true;
}
return base.OnOptionsItemSelected(item);
}
}
}
This is the main layout axml where the navigation and drawer are set the header is called in the navigation.
main.axml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- The main content view -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar_layout" />
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header"
app:menu="#menu/nav_menu" />
</android.support.v4.widget.DrawerLayout>
This is my the nav_header which I have called in the navigation view, which contains the textview which I'm trying to change on main activity.
nav_header.axml
<TextView
android:id="#+id/UserNameTxt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Username"
android:textAppearance="#style/TextAppearance.AppCompat.Body1" />
</LinearLayout>
The name doesn't change, please help.
You use LayoutInflator to inflate a view from nav_header, which means you created a total new View from nav_header.xml and changed it's sub textview's text and didn't use this new view in your activity. Thus the text of your original activity won't change.
solution:
Modify your activity codes like this:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.main);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
if (toolbar != null)
{
SetSupportActionBar(toolbar);
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetHomeButtonEnabled(true);
}
drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout); SupportActionBar.SetHomeAsUpIndicator(Resource.Drawable.ic_menu);
navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
//LayoutInflater inflater = (LayoutInflater)GetSystemService(Context.LayoutInflaterService);
//View view = inflater.Inflate(Resource.Layout.nav_header, null);
//UserNameTxt = view.FindViewById<TextView>(Resource.Id.UserNameTxt);
//UserNameTxt.Text = "Yousuf";
LinearLayout header=(LinearLayout)navigationView.GetHeaderView(0);
UserNameTxt = header.FindViewById<TextView>(Resource.Id.UserNameTxt);
UserNameTxt.Text = "Yousuf";
...
I have to display the following table:
So I want to know what is the best widget to use for the table. I want the table to be dynamic I mean if I choose some other group from the dropdown the number of items in the table to increase or to decrease and the total price to change depending on what I have in column price. What widget is the best widget to achieve that?
RecyclerView is the best UI control to achieve it. Because RecyclerView is Adapter pattern, so you can use the adapter to achieve dynamic what you have said.
I want the table to be dynamic I mean if I choose some other group from the dropdown the number of items in the table to increase or to decrease and the total price to change depending on what I have in column price
I have made a demo for you, you can test it and do some changes for your project:
Three .axml files:
Main.axml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:id="#+id/bt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="group1"/>
<Button
android:id="#+id/bt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="group2"/>
<Button
android:id="#+id/bt3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="group3"
/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
item_layout, every item's layout:
<?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="wrap_content">
<TextView
android:id="#+id/item_tv"
android:layout_width="match_parent"
android:textSize="30dp"
android:layout_height="wrap_content" />
</LinearLayout>
item_layout, total price's layout:
<?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="wrap_content">
<TextView
android:id="#+id/foot_tv"
android:gravity="end"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity:
using Android.App;
using Android.Widget;
using Android.OS;
using System;
using System.Collections.Generic;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Content;
namespace RecycleTest
{
[Activity(Label = "RecycleTest", MainLauncher = true)]
public class MainActivity : Activity
{
RecyclerView mRecyclerView;
MyAdapter adapter;
Button bt1, bt2, bt3;
List<double> list1, list2, list3;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
initView();
initData();
mRecyclerView = FindViewById<RecyclerView>(Resource.Id.rv);
mRecyclerView.SetLayoutManager(new LinearLayoutManager(this));
adapter = new MyAdapter(this, list1);
mRecyclerView.SetAdapter(adapter);
}
private void initData()
{
list1 = new List<double>();
list2 = new List<double>();
list3 = new List<double>();
list1.Add(1.1);
list1.Add(1.2);
list1.Add(1.3);
list2.Add(2.1);
list2.Add(2.2);
list2.Add(2.3);
list2.Add(2.4);
list3.Add(3.1);
list3.Add(3.2);
list3.Add(3.3);
list3.Add(3.4);
list3.Add(3.5);
}
public void initView() {
bt1 = FindViewById<Button>(Resource.Id.bt1);
bt2 = FindViewById<Button>(Resource.Id.bt2);
bt3 = FindViewById<Button>(Resource.Id.bt3);
bt1.Click += Bt1_Click;
bt2.Click += Bt2_Click;
bt3.Click += Bt3_Click;
}
private void Bt3_Click(object sender, System.EventArgs e)
{
adapter.change(list3);
}
private void Bt2_Click(object sender, System.EventArgs e)
{
adapter.change(list2);
}
private void Bt1_Click(object sender, System.EventArgs e)
{
adapter.change(list1);
}
}
class MyViewHolder : RecyclerView.ViewHolder
{
public TextView mtv;
public MyViewHolder(View itemView): base(itemView)
{
mtv = itemView.FindViewById<TextView>(Resource.Id.item_tv);
}
}
class MyFootViewHolder : RecyclerView.ViewHolder
{
public TextView mtv;
public MyFootViewHolder(View itemView):base(itemView)
{
mtv = itemView.FindViewById<TextView>(Resource.Id.foot_tv);
}
}
class MyAdapter :RecyclerView.Adapter{
Context mContext;
List<double> mList=new List<double>();
public override int ItemCount => mList.Count + 1;
public MyAdapter(Context context, List<Double> list)
{
this.mContext = context;
this.mList.AddRange(list);
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
if (GetItemViewType(position) == 0)
{
((MyViewHolder)holder).mtv.Text=(mList[position].ToString());
}
else
{
double price = 0;
for (int i = 0; i < mList.Count; i++)
{
price += mList[i];
}
((MyFootViewHolder)holder).mtv.Text=price + "";
}
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
RecyclerView.ViewHolder holder;
if (viewType == 0)
{
holder = new MyViewHolder(LayoutInflater.From(mContext).Inflate(Resource.Layout.item_layout, parent, false));
}
else
{
holder = new MyFootViewHolder(LayoutInflater.From(mContext).Inflate(Resource.Layout.foot_layout, parent, false));
}
return holder;
}
public override int GetItemViewType(int position)
{
int type;
if (position != mList.Count)
{
type = 0;
}
else
{
type = 1;
}
return type;
}
public void change(List<Double> list1)
{
mList.Clear();
mList.AddRange(list1);
NotifyDataSetChanged();
}
}
}
I am working in Xamarin android, i want to show google place autocomplete fragment in google map fragment, am using this below code but it getting error, anyone can help to solve this?
Android.Views.InflateException: Binary XML file line #1: Error
inflating class fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/googlemap"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment">
<fragment
android:id="#+id/place_autocomplete_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment" />
</fragment>
</LinearLayout>
namespace test
{
[Activity(Label = "CommuteX", MainLauncher = true, Icon = "#mipmap/icon", Theme = "#android:style/Theme.Holo.Light.NoActionBar.Fullscreen")]
public class MainActivity : FragmentActivity, IOnMapReadyCallback, IPlaceSelectionListener, IOnConnectionFailedListener
{
private GoogleMap GMap;
public void OnConnectionFailed(ConnectionResult result)
{
throw new NotImplementedException();
}
public void OnError(Statuses status)
{
Log.Info("xamarin", "An error occurred: " + status);
}
public void OnMapReady(GoogleMap googleMap)
{
this.GMap = googleMap;
LatLng latlng = new LatLng(Convert.ToDouble(12.733027), Convert.ToDouble(77.83016));
CameraUpdate camera = CameraUpdateFactory.NewLatLngZoom(latlng, 15);
GMap.MoveCamera(camera);
MarkerOptions options = new MarkerOptions().SetPosition(latlng).SetTitle("Hosur");
GMap.AddMarker(options);
}
public void OnPlaceSelected(IPlace place)
{
var placeadd = place.AddressFormatted;
var placename = place.NameFormatted;
var namadd = placename + "," + placeadd;
var latlng = place.LatLng;
Log.Info("xamarin", "Place: " + namadd);
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
SetUpMap();
var mGoogleApiClient = new GoogleApiClient
.Builder(this)
.AddApi(PlacesClass.GEO_DATA_API)
.AddApi(PlacesClass.PLACE_DETECTION_API)
.EnableAutoManage(this, this)
.Build();
PlaceAutocompleteFragment autocompleteFragment = (PlaceAutocompleteFragment)FragmentManager.FindFragmentById(Resource.Id.place_autocomplete_fragment);
autocompleteFragment.SetOnPlaceSelectedListener(this);
}
private void SetUpMap()
{
if (GMap == null)
{
FragmentManager.FindFragmentById<MapFragment>(Resource.Id.googlemap).GetMapAsync(this);
}
}
}
}