Android custom reusable controls? - android

I have a few activities in an app I'm writing that I want to put a form on the page. It's the same form for all the activities that does the same except for different title and text.
Instead of rewriting the controls and the logic for each activities I'm looking for a way to create my own control that I can put in my layout xml files with my own properties so all I'll need to do is write it once and use that control where I need to.
how can I do such a thing?
Thanks

What about writing your control as an android Fragment? In the xml you can declare a FrameLayout and then insert the fragment inside it using the replace() method of FragmentTransaction.

You can use an Activity which extends android.app.Activity and define it the common logic.Then all your other activities will extend it in place of extending android.app.Activity. Then they will inherit it , and you can override what you want to Override as well.
This solution is not bad if you have exactly the same layout and just some differences, you can load the layout.xml only once and then use it in the child class as you like.
SuperClass :
public SuperClass extends Activity{
protected TextView myTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
myTextView = (TextView) findViewById(R.id.my_text_view);
}
}
ChildClassA :
public ChildClassA extends SuperClass {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
myTextView.setText("I am in A");
}
}
ChildClassB :
public ChildClassB extends SuperClass {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
myTextView.setText("I am in B");
}
}
Other suggestion:
Another idea is to create a custom view. see this tutorial also.

Depends on what differences you have in each Activity and how you access them.
If it's only some strings, that are different, put those strings inside the Intent, which starts the Activities and grab them in onCreate().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lyt_template_form);
((TextView) findViewById(R.id.txt_form_headline)).setText(getIntent().getStringExtra("headline");
((TextView) findViewById(R.id.txt_form_subtitle1)).setText(getIntent().getStringExtra("subtitle1");
//etc...
If there are more differences in your control code and you need to distinguish some kind of "Form Type A", "Form Type B", etc., you can put an indicator inside your Intent and check for that to make different decisions in your code.
So e.g.
if (getArguments().getInt("Type") == 0) {
// do stuff in control like this
} else if (getArguments().getInt("Type") == 1) {
// do stuff in control like this
// etc.
getArgument() is the equivalent of getIntent().getXyzExtra()

Related

Setting Background Colour to PreferenceActivity

I am having a confusion regarding setting of a background colour in my preference activity. My settingsactivity doen't have any layout.xml attached with it and thus generated everything from the headers.xml and preferences.xml. I used this answer in my onCreate method of my settingsactivity class.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
this.getWindow().getDecorView().setBackgroundColor(0xFF111321);
}
Using this I can see the change in my preferences (sorry for the colour) but my headers headers stay the same. To change the background of my headers I have to write:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
this.getWindow().getDecorView().setBackgroundColor(0xFF111321);
listView = getListView();
listView.setBackgroundColor(0xFF111321);
}
Also if I don't use getWindow() the opposite happens.
Why is this happening?
I hate writing duplicate code for the same functionality, is there any way to do the requirement with a single code.
N.B. getWindow() also works with my other activities.

Android Activity, extend BaseActivity

What would be the correct way of implementing my idea? Should I use inflate?
Want to make aprox. 100 activities. All of them extending the same base-class (BaseActivity). What I want to accomplish is a BaseActivity that will show 3 View's (LeftView, MainView, RightView) in a LinearLayout (horizontal). This is not the problem. MainView is empty.
The problem arises when I want to design MyActivity (extends BaseActivity). My idea was that the R.layout designed in MyActivity ONLY was shown in MainView (part of BaseActivity).
Is this possible? and what would be the smartes/best way to implement this?
Kind regards, Ole
OK, the way I choose to handle this, was by inflating the R.layout:
public class BaseActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.base_activity);
return;
}
}
public class MyActivity extends BaseActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
RelativeLayout da_layout_main = (RelativeLayout) findViewById( R.id.da_layout_main);
View view_child = getLayoutInflater().inflate( R.layout.my_activity, null);
da_layout_main.addView( view_child);
}
}

Fragment placed on top of NavigationDrawer

I'm trying to add a PreferenceFragmentin my application. The problem is, it's auto placed on top of my NavigationDrawer.
public class SetPreferenceActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
navigationDrawer(); // Loads the NavigationDrawer
getFragmentManager().beginTransaction().replace(android.R.id.content,
new Settings()).commit();
}
As you can see I load the "SettingsFragment" and replace the content with it? (I'm unsure) but it places it on top of everything else.. Here's my Settings fragment.
public class Settings extends PreferenceFragment {
static final String TAG = "MAIN";
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
Everything work as expected, BUT the PreferenceFragment are loaded in front, covering up the NavigationDrawer slideout, I tried calling bringToFront(); on the listview, with no luck.
A picture for reference :
Is it possible to tell the fragment to load behind the listview? I also tought about loading the fragment in a ViewPager, but I get an error that the Pager Adapter wont accept fragments of type PreferenceFragment.
Don't replace android.R.id.content, use the the id of the FrameLayout you have in the layout that contains your DrawerLayout.
In addition to what adneal said (in case others have the same problem):
The Activity which calls the PreferenceFragment needs to have the setContentView() method if you extend the Activity with your NavigationDrawer:
public class SetPreferenceActivity extends MyNavigationDrawer {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
getFragmentManager().beginTransaction().replace(R.id.drawer_frame_layout,
new Settings()).commit();
}
And the settings.xml should only contain a FrameLayout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
I had same issue and i resolved it by replacing android.R.id.content to R.id.container.

findViewById() returns null

There are a few questions already asking about this, but I'm not finding a solution. I have a LiveWallpaper that is using its own subclass of PreferenceFragment to specify preferences. The solution most often cited is to assure that setContentView() is called before findViewByID(). I am not calling setContentView() at all because I do not have a layout specified. This app originally implemented the preferences using the deprecated methods like PreferenceActivity.getPreferenceManager() and without using a layout and worked just fine. I am trying to bring the code up-to-date in using PreferenceFragment.
Am I required to have a layout and if so, what would I have when I don't really want one?
Or is there a another way to get/set the View?
public class SetPreferenceActivity extends Activity {
private CheckBox redCheckBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main); ???
redCheckBox = (CheckBox)findViewById(R.id.redCheckBox); // returns null
getFragmentManager().beginTransaction().replace(android.R.id.content, new LiveWallpaperPreferenceFragment()).commit();
}
}
You can create views dynamically :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
textView.setText("Hello");
setContentView(textView);//<----set the view !
}
}

Save state of activity when orientation changes android

I have an aacplayer app and I want to save the state of my activity when orientation changes from portrait to landscape. The TextViews do not appear to be empty, I tried to freeze my textview using this:
android:freezesText="true"
my manifest:
android:configChanges="orientation"
I also tried this:
#Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main2);
So when orientation changes to landscape I can see my layout-land main2.xml, that works but my textview goes out and appears empty. Streaming music works great. I can listen to it when orientation changes, but the text inside textviews are gone each time I change the orientation of my device.
What should I do to fix this so I can save the state?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
....
Thank you very much.
When your orientation changes, you don't have to manually change to the landscape layout file. Android does this automatically for you. When orientation changes, Android destroys your current activity and creates a new activity again, this is why you are losing the text.
There are 2 parts you need to do, assuming you want a separate layout for portrait and landscape.
Assuming you have 2 XML layout files for portrait and landscape, put your main.xml layout file in the following folders:
res/layout/main.xml <-- this will be your portrait layout
res/layout-land/main.xml <-- this will be your landscape layout
That's all you need to do, you don't have to touch the manifest file to modify android:configChanges="orientation" or override the onConfigurationChanged(). Actually, it's recommended you do not touch this for what you are trying to achieve.
Now to save your text from the text view =) Lets assume your textview is named as MyTextView in your layout xml file. Your activity will need the following:
private TextView mTextView;
private static final String KEY_TEXT_VALUE = "textValue";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextView = (TextView) findViewById(R.id.main);
if (savedInstanceState != null) {
CharSequence savedText = savedInstanceState.getCharSequence(KEY_TEXT_VALUE);
mTextView.setText(savedText);
}
}
#Override
protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putCharSequence(KEY_TEXT_VALUE, mTextView.getText());
}
Basically, whenever Android destroys and recreates your Activity for orientation change, it calls onSaveInstanceState() before destroying and calls onCreate() after recreating. Whatever you save in the bundle in onSaveInstanceState, you can get back from the onCreate() parameter.
So you want to save the value of the text view in the onSaveInstanceState(), and read it and populate your textview in the onCreate(). If the activity is being created for the first time (not due to rotation change), the savedInstanceState will be null in onCreate(). You also probably don't need the android:freezesText="true"
You can also try saving other variables if you need to, since you'll lose all the variables you stored when the activity is destroyed and recreated.
There are two ways of doing this, the first one is in the AndroidManifest.xml file. You can add this to your activity's tag
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
Or you can override two methods that will take care of this. This method requires some more effort, but arguably is much better. onSaveInstanceState saves the state of the activity before it's killed, and onRestoreInstanceState restores that information after onStart() Refer to the official documentation for a more in depth look.
In my sample code below, I am saving 2 int values, the current selection from the spinner as well as a radio button.
#Override
public void onSaveInstanceState(#NonNull Bundle savedInstanceState) {
spinPosition = options.getSelectedItemPosition();
savedInstanceState.putInt(Constants.KEY, spinPosition);
savedInstanceState.putInt(Constants.KEY_RADIO, radioPosition);
super.onSaveInstanceState(savedInstanceState);
}
// And I am restoring those values with `getInt`, then I can pass those stored values into the spinner and radio button group to select the same values that we saved earlier.
#Override
public void onRestoreInstanceState(#NotNull Bundle savedInstanceState) {
spinPosition = savedInstanceState.getInt(Constants.KEY);
radioPosition = savedInstanceState.getInt(Constants.KEY_RADIO);
options.setSelection(spinPosition, true);
type.check(radioPosition);
super.onRestoreInstanceState(savedInstanceState);
}
static CharSequence savedText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedText != null) {
TextView mTextView = (TextView) findViewById(R.id.main);
mTextView.setText(savedText);
}
}
// Another function in activity, when you change text
public void actionButton(View view) {
// Change and save text in textView
savedText = "Change text";
mTextView.setText(savedText);
}
Its work for me.
But I think its not good code style and architecture for android.
I use in KOTLIN static var / val :
class MyFragment : Fragment()
{
//all my code
//access to static vars -> MyStaticClass.hello
}
class MyStaticClass
{
companion object {
var hello: String = "Static text"
var number_static: Int = 0
}
}

Categories

Resources