Xamarin + MvvmCross 6.0 unable to implement tabs navigation - xamarin

I'm building a simple Xamarin app using MvvmCross and I'm currently unable to implement tabs navigation.
I'm getting an Mvx Exception: viewpager or tablayout not found
This is my main activity:
[MvxActivityPresentation]
[Activity(Theme = "#style/MainTheme",ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation |
Android.Content.PM.ConfigChanges.ScreenSize)]
public class TabsRootView : MvxAppCompatActivity<TabsRootViewModel>
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.tabs_root_view);
if (bundle == null)
{
ViewModel.ShowInitialViewModelsCommand.Execute();
}
}
}
This is my tabs root view layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
local:popupTheme="#style/ThemeOverlay.AppCompat.Light"
local:layout_scrollFlags="scroll|enterAlways">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
local:tabGravity="center"
local:tabMode="scrollable" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
local:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
This is supposed to be one of my tabs content fragment (the other one looks the almost the same):
[MvxTabLayoutPresentation(TabLayoutResourceId = Resource.Id.tabs, ViewPagerResourceId = Resource.Id.viewpager, Title = "Bacheca", ActivityHostViewModelType = typeof(TabsRootViewModel))]
[Register(nameof(PostsView))]
public class PostsView : MvxFragment<PostsViewModel>
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
var view = this.BindingInflate(Resource.Layout.posts_view, null);
// RecyclerView
var recyclerView = view.FindViewById<MvxRecyclerView>(Resource.Id.recycler_view);
recyclerView.SetLayoutManager(new LinearLayoutManager(Activity));
recyclerView.HasFixedSize = false;
// Swipe touch helper
var callback = new SwipeItemTouchHelperCallback(ViewModel);
var touchHelper = new ItemTouchHelper(callback);
touchHelper.AttachToRecyclerView(recyclerView);
return view;
}
}

Related

XAMARIN : programatically created layout lost during page navigation between different activities

I have created a Xamarian Form.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<ScrollView
android:id="#+id/configureScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/dynamicLinearlayout"
android:orientation="vertical"/>
</ScrollView>
</LinearLayout>
Programatically added a layout to Linearlayout inside the ScrollView.
LinearLayout dynamicL;
protected override void OnCreate(Bundle savedInstanceState)
{
//.....
dynamicL = FindViewById<LinearLayout>(Resource.Id.dynamicLinearLayout);
}
var layout = new LinearLayout(this);
layout.Orientation = Orientation.Horizontal;
layout.Id = 500;
Button btnRemove = new Button(this);
btnRemove.Text = "-";
btnRemove.TextAlignment = TextAlignment.Center;
layout.AddView(btnRemove);
//Add to scroll layout
dynamicL.AddView(layout);
As soon as I navigate to another page and come back it looses the layout. how can i save it?
After dynamically adding views to page.
Once I navigate to home page and comes back.
I create one sample about navigation between different activities, and come back, the layout still appear, please take a look the following code.
Activity_main.xml:
<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"
android:orientation="vertical">
<ScrollView
android:id="#+id/configureScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/dynamicLinearlayout"
android:orientation="vertical"/>
</ScrollView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="btn"
android:id="#+id/button1"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="navigation"
android:id="#+id/button2"/>
</LinearLayout>
MainActivity.cs:
public class MainActivity : AppCompatActivity
{
private Button btn;
private LinearLayout dynamicL;
private Button btn1;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
btn = FindViewById<Button>(Resource.Id.button1);
btn.Click += Btn_Click;
btn1 = FindViewById<Button>(Resource.Id.button2);
btn1.Click += Btn1_Click;
dynamicL = FindViewById<LinearLayout>(Resource.Id.dynamicLinearlayout);
}
private void Btn1_Click(object sender, EventArgs e)
{
var intent = new Intent(this, typeof(Activity1));
StartActivity(intent);
}
private void Btn_Click(object sender, EventArgs e)
{
var layout = new LinearLayout(this);
Button btn = new Button(this);
btn.Text = "btn";
btn.TextAlignment = Android.Views.TextAlignment.Center;
layout.AddView(btn);
dynamicL.AddView(layout);
}
}
When click Button to navigate to another activity, come back button in device, layout still appear.

Xamarin. SetContentView() in FormsAppCompatActivity throws unhandled exception

When atempting to run this code in a xamarin forms app, I get the following exception:
Android.Content.Res.Resources+NotFoundException: Unable to find resource ID #0x1
[Activity(Label = "Xamarin Forms", Icon = "#drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.main);
Toolbar toolbar = this.FindViewById<Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
}
...
If I inherit from AppCompatActivity instead the app does not crash but the forms apis are not available any more.
Here is my layout file in case it helps:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/main_content"
android:layout_below="#id/toolbar" />
</RelativeLayout>

RecyclerView item dynamic Height micro stutter

I use an EndlessAdapter with a RecyclerView to fetch and load few hundred items from server.
Glide takes care to load the images for each row.
If user scrolls slowly, everything works fine, but when he flings, there are some micro stuttering in scrolling.
I think that this happens due to different image height for each row, but I don't know how to eliminate it.
My adapter code:
public final class ImagesAdapter extends EndlessAdapter<Image, ImagesAdapter.imageHolder> {
#NonNull
private static Fragment mFragment;
private OnItemClickListener onItemClickListener;
private static int mScreenWidth;
private int layoutStyle;
public ImagesAdapter(#NonNull Fragment fragment, List<Image> images, int layoutStyle) {
super(fragment.getActivity(), images == null ? new ArrayList<Image>() : images);
mFragment = fragment;
setHasStableIds(true);
mScreenWidth = fragment.getResources().getDisplayMetrics().widthPixels;
this.layoutStyle = layoutStyle;
}
public void changeLayout(int layoutStyle){
this.layoutStyle = layoutStyle;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
#Override
public long getItemId(int position) {
return (!isLoadMore(position)) ? mItems.get(position).getId() : -1;
}
#Override
protected imageHolder onCreateItemHolder(ViewGroup parent, int viewType) {
final imageHolder holder;
switch (layoutStyle) {
case 0:
default:
holder = new imageHolder(mInflater.inflate(R.layout.item_image_enhanced_optim, parent, false));
break;
case 1:
holder = new imageHolder(mInflater.inflate(R.layout.item_image, parent, false));
break;
}
return holder;
}
#Override
protected ProgressViewHolder onCreateItemProgressBarHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
return new ProgressViewHolder(v);
}
#Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
super.onViewRecycled(holder);
if (holder instanceof ProgressViewHolder) {
((ProgressViewHolder) holder).progressBar.stop();
Timber.d("Stopped progressbar");
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == VIEW_TYPE_ITEM) {
((imageHolder) holder).bind(mItems.get(position));
} else {
((ProgressViewHolder) holder).start();
}
}
public void shuffle(List<Image> images) {
mItems.clear();
this.mItems.addAll(images);
notifyDataSetChanged();
}
final class imageHolder extends RecyclerView.ViewHolder {
#Bind(R.id.item_image_content)
FrameLayout container;
#Bind(R.id.item_image_img)
ImageView mImageView;
#Bind(R.id.item_image_name)
TextView imageName;
#Bind(R.id.item_author_name)
TextView imageAuthorName;
#Bind(R.id.item_author_image)
CircleImageView userImage;
#Bind(R.id.item_image_date)
TextView imageDate;
#Bind(R.id.item_image_comments)
TextView comments;
#Bind(R.id.item_view_on_map)
LinearLayout viewOnMap;
#Bind(R.id.item_view_share)
LinearLayout share;
#Bind(R.id.moreView)
LinearLayout moreView;
#Bind(R.id.progress_image)
LoadingView loadingView;
public imageHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
public void bind(#NonNull final Image image) {
container.setOnClickListener(new onImageClickListener(getAdapterPosition()));
userImage.setOnClickListener(new onAuthorClickListener(userImage, getAdapterPosition()));
viewOnMap.setOnClickListener(new onViewOnMapClickListener(getAdapterPosition()));
share.setOnClickListener(new onShareClickListener(getAdapterPosition()));
moreView.setOnClickListener(new onMoreClickListener(getAdapterPosition()));
loadingView.setVisibility(View.VISIBLE);
imageName.setText(image.getCombinedTitle());
imageAuthorName.setText(image.getAuthor());
imageDate.setText(image.getReadableDate());
comments.setText(image.getComments());
if(!loadingView.isCircling())
loadingView.start();
Glide.with(mFragment)
.load(image.getImageSrc(mScreenWidth))
.crossFade()
.override(mScreenWidth, (int) ((float) mScreenWidth / image.getRatio()))
.listener(new RequestListener<String, GlideDrawable>() {
#Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
loadingView.stop();
loadingView.setVisibility(View.GONE);
return false;
}
})
.into(mImageView);
}
}
and the row item
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
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:id="#+id/main_container"
android:layout_marginBottom="5dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="5dp"
app:cardCornerRadius="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white">
<FrameLayout
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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/light_gray"
android:orientation="vertical">
<ImageView
android:id="#+id/item_image_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
tools:src="#drawable/header"
android:contentDescription="#string/img_content"
android:scaleType="fitXY" />
<FrameLayout
android:id="#+id/item_image_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:foreground="?selectableItemBackgroundBorderless"
android:orientation="vertical" />
</FrameLayout>
<include layout="#layout/item_image_header"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_marginLeft="47dp"
android:visibility="visible"
android:paddingRight="10dp"
android:layout_marginBottom="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:gravity="center_vertical">
<ImageView
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginRight="3dp"
android:contentDescription="#string/descr" />
<TextView
android:id="#+id/item_image_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textColor="#color/colorPrimary"
android:textSize="15.0sp"
android:layout_gravity="center_vertical" />
</LinearLayout>
<TextView
android:id="#+id/item_image_comments"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:ellipsize="end"
android:maxLines="4"
tools:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:textColor="#android:color/primary_text_light_nodisable"
android:textSize="13.0sp"
android:layout_marginBottom="10dp" />
</LinearLayout>
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:background="#drawable/divider_shape"
android:layout_height="0.5dp" />
<include layout="#layout/item_image_bottom_buttons"/>
</LinearLayout>
Glide stop loading Images When you scroll list very fast it is done to improve the speed of Scrolling and avoiding any jitter
If you want to show images to your user I suggest you to use Picasso.
https://github.com/square/picasso
However Picasso is not good in caching the Images or has a limited Caching
or Either way u use placeHolder to represent the Image.
Edit
Heads up u can do it easily with Glide
Glide.with(getActivity())
.load("http://www.mediafile.com/12364f")
.placeholder(R.drawable.circle_placeholder_drawable)//this will show this image till your image is not fully loaded
.error(R.drawable.error_drawable)// if there is a problem in loading image an error image would be loaded instead
.into(holder.mFileTransferCircleImageView);

Sending sms app inside a Fragment

I'm creating an android using fragments .I have created a an sms fragment for sending sms to a specific number but when it runs well but when i type the message then press send , the app crashes and closes. help me out.
public class SMS extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// View v = inflater.inflate(R.layout.fragment, null);
View v = inflater.inflate(R.layout.sms, container, false);
return v;
}
public void sendsms(View v)
{
//refernce the edittext
EditText message=(EditText) v.findViewById(R.id.Messege);
//get the phone the number and the message
String number="0712345678";
String msg=message.getText().toString();
//use the sms manager to send message
SmsManager sm=SmsManager.getDefault();
sm.sendTextMessage(number, null, msg, null, null);
Toast.makeText(getActivity(),"Messege sent",Toast.LENGTH_LONG).show();
}
}
the following is the xml layout that I have used.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:background="#drawable/log"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send your feedback" />
<EditText
android:id="#+id/Messege"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:hint="Enter your messege"
android:layout_marginTop="15dp"
android:ems="10" >
</EditText>
<Button
android:id="#+id/send"
android:onClick="sendsms"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send SMS" />
</LinearLayout>
The onClick() method is run in the UI thread. You don't want to send an SMS message from the UI thread. Try wrapping your sendSMS code in an AsyncTask or create a new Thread to run that code.

The child views of the my parent ViewGroup remains unchanged and gets displayed in my new inflated layout at the bottom

Inflation using Array Adapter - The inflated layout does not fill my full screen.
The views present in the parent View Group get displayed at the bottom of my newly inflated layout. The inflation is not fitting full screen and causing display issues as in the image. Code is working fine but i am having problem with my Display. Please suggest possible solution. The parent XML is also an inflated layout list(Array Adapter).
Note
The layout is properly inflated by setting attachRoot=false
(Inflater.inflate(R.layout.chapterlayout, parent, false)).
Cannot process ViewGroup from ArrayAdapter , so unable to remove the parent views.
INFLATED XML 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="match_parent"
android:background="#drawable/my_background"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="100" >
<TextView
android:id="#+id/ENo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="90"
android:text="1."
android:textColor="#0000FF"
android:textSize="15sp"
android:textStyle="bold" >
</TextView>
<TextView
android:id="#+id/EA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="10"
android:paddingBottom="5sp"
android:text="My Text"
android:textColor="#0000FF"
android:textSize="15sp"
android:textStyle="bold" >
</TextView>
</LinearLayout>
<TextView
android:id="#+id/EE"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="My Text"
android:textColor="#0000FF"
android:textSize="15sp"
android:textStyle="bold" >
</TextView>
</LinearLayout>
PARENT XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/my_background">
<TextView
android:id="#+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="15sp"
android:textColor="#0000FF"
android:textStyle="bold"
android:background="#drawable/my_background">
</TextView>
</LinearLayout>
JAVA CODE
public class MyChapterAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public MyChapterAdapter(Context context, String[] values) {
super (context, R.layout.main, values);
this.context = context;
this.values = values;
}
static class ViewHolder {
TextView ENo;
TextView EA;
TextView EE;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater li = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.chapterlayout, parent, false);
holder = new ViewHolder();
holder.ENo = (TextView) convertView.findViewById(R.id.ENo);
holder.EA = (TextView) convertView.findViewById(R.id.EA);
holder.EE = (TextView) convertView.findViewById(R.id.EE);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
reDesignLayout(position, holder);
return convertView;
}
private void reDesignLayout(int position, ViewHolder h) {
// TODO Auto-generated method stub
String chapSplit[] =values[position].split("##");
h.ENo.setText(chapSplit[0]+". ");
h.EA.setText(chapSplit[1]);
h.EE.setText(chapSplit[2]);
}
}

Resources