I have this situation: an abstract activity and a series of activities that extend this one. The difference from parent activity is just a piece of layout, and some methods, how can I do with the layout? I declare 'n' very similar layout ? or I can only declare one and then extend only to the extent that change? and in this case, how?
I give you an example.
In MyAbstractActivity i call setContentView(R.layout.abstract_layout), where abstract_layout.xml has this layout:
<LinearLayout>
<Button id=1/>
<Button id=2/>
<Button id=3/>
<Button id=4/>
</LinearLayout>
Now in MyConcreteActivity that extends MyAbstractActivity suppose that we want a textfield below Button with id=2, how we can do?
Thanks in advance!
EDIT:
Solved using ViewStub in superclass and changing it in subclasses.
You would need a separate layout for each of your subclasses. Then in your subclass onCreate you could do:
setContentView(R.layout.concrete_layout_1);
super.onCreate(savedInstanceState);
And avoid calling setContentView in your abstract activity. Depending on the code you currently have in MyAbstractActivity#onCreate, you may have some refactoring to do.
In the end there isn't really a concept of inheritance for layouts, although you can do some creative things with <include ...>; you might check Creating Reusable UI Components if you care about DRY.
Related
Update - Thanks to #Martijn00 and #Plac3Hold3r I have managed to update my app to use the MvxCachingFragmentCompatActivity but it is just not working correctly. I am finding that if I go back sometimes the the ViewModel will be available, but the commands in the view model will be null.
Also if I go back and then forward, some of the buttons don't respond. I assume this is the same issue.
What I really need to know is what the additional functionality the caching activity gives me, and how to use it properly.
Original question follows...
I am hitting a problem where the view model for a fragment is null. I suspect my activity is being cleared up when I open a camera activity. For all my application am using a single activity and all my views are fragments.
When the camera activity is complete, the activity is reconstructed, but one of the fragments view model is null. I am currently using an AppCompatActivity for my single activity, but through my research I should probably be using a MvxCachingFragmentActivity. The problem is I have no idea how I am supposed to use it. I cannot find a clear explanation anywhere.
Has anyone got a working example of how to use the MvxCachingFragmentActivity or the MvxCachingFragmentCompatActivity.
I can't find anywhere where it tells me how I should use it.
I found this other link example but I think it is out of date and the other link given in this example is a 404.
If anyone knows of a simple sample and whether this will work with a single activity please let me know.
Thanks
Setup
MainActivity
Create an activity that inherits from MvxCachingFragmentCompatActivity or MvxCachingFragmentActivity.
[Activity]
public class MainActivity : BaseFragmentActivity<MainContainerViewModel>
{
}
MainContainerViewModel
Create a Viewmodel to associate to the Activity. You will never navigate directly using this Viewmodel. Instead you will navigate to this Viewmodel via the fragments that specifies MainContainerViewModel as their parent's Viewmodel.
public class MainContainerViewModel : MvxViewModel
{
}
XML layout example
Add a layout to your MainActivity. Make sure to include a FrameLayout that has an id. In this case content_frame. This id is important as this is how you will identify the frame where to place your fragment. You specify multiple FrameLayout's if you want more that one fragment for the same view.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
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="?attr/actionBarSize"
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">
<TextView
android:id="#+id/textview_toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:layout_gravity="left"
style="#style/TextAppearance.AppCompat.Widget.ActionBar.Title" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
HomeFragment
In terms of fragments you need to include the MvxFragment attribute, which needs the type of Viewmodel associate to the Activity you want to place your fragment in. Additionally, you need to specify the id for the FrameLayout that is found on the activities layout, where you want to place the fragment.
[MvxFragment(typeof(MainContainerViewModel), Resource.Id.content_frame)]
[Register(nameof(HomeFragment))]
public class HomeFragment : BaseFragment<HomeViewModel>
{
}
Usage
When navigating your can now use ShowViewModel<HomeViewModel>() which will navigate to the home fragment. But, importantly it will first start up the required Activity MainActivity before doing the fragment navigation. This allows for better shared navigation with other platforms which do not require these container Viewmodels, i.e. they get handled automatically via convention.
Notes
You can specify multiple MvxFragment attributes. Is is usefully if you want the same fragment shared under multiple Activities. The Top MvxFragment attribute will be used as the default. If you are currently in the context of any of the other matching MvxFragment attributes then navigation will take place under that activity.
If your Setup.cs is not inheriting from MvxAppCompatSetup or you are using a custom presenter, you need to make sure that you also registering your presenter against IMvxAndroidViewPresenter. This is important as MvxCachingFragmentCompatActivity or MvxCachingFragmentActivity resolve IMvxAndroidViewPresenter in order to navigate to the required fragment.
protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
var mvxFragmentsPresenter = new MvxFragmentsPresenter(AndroidViewAssemblies);
Mvx.RegisterSingleton<IMvxAndroidViewPresenter>(mvxFragmentsPresenter);
return mvxFragmentsPresenter;
}
You can also check out the Sample Repo for an example of this in use.
Hi all and thank you in advance and sorry for my english. I have two big doubts
1 - I haven't been too much time programming in android, and i pretty sure there is a lot of things i have made in wrong ways. For example, I have made several apps where in xml definition i include another xml.
For example, imagine 2 activities with a header_section.xml being include in both activities xml definition. That header_section has 5 buttons and more views etc. Ok, in the xml is just make an include and it works......but to implement the buttons.....do i have to REPEAT the code in both activities?? it sounds really bad practice to duplicate code in both activities.....but how can i do, for example this in activities A and B? Do i have to put this code exactly the same in both activities classes????
private View header_section;
private Button bExample;
header_section=findViewById(R.id.header_section);
bExample=(Button)header_section.findViewById(R.id.bExample);
bExample.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Whatwever...call a number, for example
}
});
In main xml something like:
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="0dp" >
<include android:id="#+id/header_section" android:layout_gravity="center" android:gravity="center" layout="#layout/header_section" />
</LinearLayout>
and in header_section.xml something like:
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="0dp" >
<Button android:id="#+id/bExample" />
</LinearLayout>
2 - Imagine you have like 10 activities in your app. If in all of them there are a header section and bottom section with the same functionality, changing just the central area (showing different lists, views etc)......is better have just one activitie in ALL the app, with a viewflipper in the central area? or have 10 activities having, i do not know if can be avoided, asked in point 1, code repeated in all 10 activities for the implementation of the headers and bottoms views, handlers etc?
Thanks and best regards
1) Yes, usually, you should have to use them BUT you can make it simplier...
1.a) bExample=(Button)findViewById(R.id.bExample); //don't need to load the View
1.b) You can shorten a bit how you call the onclick, in your button/clicable element inside the LAYOUT, here's an example:
<!--inside layout -->
<Button android:id="#+id/bExample" android:onClick="aceptar" />
and
//inside the Activity
public void aceptar(View v){
//here the code of the button
}
For the question about implementing the same methods inside all Activities, check this post: Adding the same context menu to multiple activities
2) Depending the application
If you don't do much, you can load all in the same activity and HIDE/SHOW the layout elements you don't want.
But it's better to use different activities, anyway, if the layout is not "heavy" (too many elements/includes inside) you can load the SAME layout for all your activites, and you only need to change the different contents (strings) and/or HIDE/SHOW the different elements.
Im keeping CustomScrollView inherited from HorizontalScrollView inside my MyActivity which extends FragmentActivity.While Running the App, it causes ClassNotFoundException - packagename.MyActivity.CustomScrollView not found!!...
How to solve this??
Thanx in advance!!
You wanna refer to your custom scroll view as
<view class="packagename.MyActivity$CustomScrollView" />
Or possibly
<ViewGroup class="packagename.MyActivity$CustomScrollView" />
considering you're implementing a container. The reason it needs to be in a class attribute rather than the usual tag name style is that $ is needed to refer to nested classes, and $'s an illegal character in xml tag names.
Also note that MyActivity.CustomScrollView needs to be declared as public and static within MyActivity.
not packagename.MyActivity.CustomScrollView
try
packagename.MyActivity$CustomScrollView
You said CustomScrollView is inside MyActivity, right?
I think you want this:
<com.tabs.MyActivity$CustomScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:scrollbars="none" >
</com.tabs.MyActivity$CustomScrollView>
notice the $ instead of the .
I'm a beginner at android programming, so excuse me if my wording is slightly incorrect.
I have a custom canvas view along with a TextView inside a linear layout, defined in the layout file as
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="#+id/blah"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:gravity="top|center_horizontal"
/>
<com.*.Overlay android:id="#+id/combined"
android:layout_width="fill_parent"
android:layout_height="100dp"
/>
</LinearLayout>
I need to be able to read the text contained in the TextView from within the Overlay custom class that I created.
(The overlay class takes in 2 bitmaps and puts one on top of the other. The bitmaps used will depend on the text in the TextView.)
I considered using intents, but the Overlay class doesn't have an onCreate method.. All my code is within the onDraw method. I also added the necessary constructors.
I'm not sure what to try next, perhaps try accessing the parent linearlayout and then its child textview?
Hope I managed to explain everything in a non-confusing manner
Ok, managed to fix the issue... sort of
I found out that Views need to be contained in Activities.. so I created a new Activity with my custom view as an inner class, passed an intent with the necessary data to the activity and was able to use it successfully in my custom canvas view.
I was a bit surprised I didn't get any responses, but I guess that's because I'm new here
I am using the method setKeepScreenOn(true) and haven't been able to figure out how to call this in relation to the current Activity (which has a content view set). I've been able to get it to work by calling it on one of my buttons which is always present in the view, but this feels wrong - and I'm sure there must be a way to get around this. I tried referencing the current focus like this:
getCurrentFocus().setKeepScreenOn(true);
but that threw a NullPointerException. Maybe there was no current focus.
So, can anyone tell me how I can reference the view class which I am working inside? Thanks :)
Try this answer:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow is a method defined for activities, and won't require you to find a View first.
As Hawk said but poorly explained.
You can also use FLAG_KEEP_SCREEN_ON in your XML layout file.
Note the android:keepScreenOn="true"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:keepScreenOn="true"
android:orientation="vertical" >
<!-- whatever is in your layout -->
</LinearLayout>
I've now written all the choices for keeping the screen on up into a blog post:
http://blog.blundellapps.com/tut-keep-screen-onawake-3-possible-ways/
Set android:keepScreenOn in XML
If you are doing it on a class extends View. You can simple:
this.setKeepScreenOn(true);
According to Google Docs for android Developers you've two ways to do this :
First way :
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
Second way is to add in your xml file layout this attribute:
android:keepScreenOn="true"