Changing Title from Activities present in tabs in TabLayout in Android - android

Im trying to change the title from the activities inside the Tab. but the title remains same as the Title given for TabActivity. I searched for the solution but not succeeded yet. is there a way to do it? please help me on this.
Thanks

In an Activity used as child of a TabActivity you can use simply
getParent().setTitle("your title");
the getParent will return the current instance of TabActivuty, than you can change the title

You could use the singleton methodology with the TabActivity, then use This Method to change the title.
MyTabs.java
class MyTabs extends TabActivity {
private static MyTabs theInstance;
public static getInstance() {
return MyTabs.theInstance();
}
public MyTabs() {
MyTabs.theInstance = this;
}
...
}
ActivityInTab.java
...
TabActivity tabActivity = MyTabs.getInstance();
((TextView)tabActivity.getTabHost().getTabWidget().getChildAt(0).findViewById(android.R.id.title)).setText("New");
...
(Obviously this isn't a complete singleton implementation, but it will suffice for what you're doing. Since the activity can't exist without the parent container, it's safe to assume a reference has been set in the constructor when the object was created.)

Related

How to reuse the code in android

I'm trying to reduce the double effort of using the duplicate code. I searched on the google but didn't found about it that how we can reduce the duplication of code in android. May be this question could be stupid but I want the clarification.
1) The first thing I want to ask is that how we can reuse the same code in the multiple activity which are being using in overriden method as onBackPressed() onOptionsItemSelected() and so on. Here is the code which I'm currently writing in the onBackPressed() method.
#Override
public void onBackPressed(){
if(this.mDrawerLayout.isDrawerOpen(GravityCompat.START)){
this.mDrawerLayout.closeDrawer(GravityCompat.START);
}else{
super.onBackPressed();
}
}
For this approache I get the suggestion from this question to make the base activity then override this method after that extends other activities from that BaseActivity. But how I can pass the mDrawerLayout field in the BaseActivity? how I can use findViewById() on that base activity to access the xml widgets to access in the overriden method as currently using mDrawerLayout layout.
Example in code.
public BaseActivity extends AppCompatActivity{
private DrawerLayout mDrawerLayout; // how to initialize it? where to call findViewById?
#Override
public void onBackPressed(){
if(this.mDrawerLayout.isDrawerOpen(GravityCompat.START)){
this.mDrawerLayout.closeDrawer(GravityCompat.START);
}else{
super.onBackPressed();
}
}
}
The same question for the onOptionsItemSelected() mean menu item actions.
2) The second duplication I'm facing about hundred of time is startActivity() I have to write Intent then add the extra data if required than use that Intent. so about 2 to 3 lines I have to write again and again.
3) This thing is about the XML, I'm using the value 5dp or 10dp or 10sp or other dimen values in the XML file which are repeating a lot of time. So I want to ask is this approach will be Ok?
<dimen name="ten_dp">10dp</dimen>
android:layout_margin="#dimen/ten_dp"
Mean declare the dp value then use that in the XML.
Edited:
4) This problem I have faced now. I'm using the same toolbar in all activities and after adding it in XML layout I have to write this code.
private void setupToolbar(){
setSupportActionBar(mainToolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
}
But I have to re-write/copy the code in all activities. What is the solution of this problem?
1) For your first question, you'd have to have mDrawerLayout in your BaseActivity, then you'd attach your child activity's DrawerLayout into that field on the child activity's onCreate():
super.mDrawerLayout = findViewById(R.id.drawer_layout)
You can also do that for other #Override methods, such as onOptionsItemSelected().
Example based on your BaseActivity class:
public class MainActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawer_layout);
}
}
Also, make your BaseAcitivity abstract to avoid the "add to manifest warning":
public abstract class BaseActivity extends AppCompatActivity
2) As for your second question, I'd say that in your BaseActivity you could have a public method called getIntent() which would return a common Intent object. You'd then call that method from your child Activity.
You can pretty much have any method with common functionalities on your BaseActivity.
3) From my personal experience, it is counterproductive to declare resource values that does not represent the purpose of itself, such as yours: <dimen name="ten_dp">10dp</dimen>. I'd rather name it based on a representative use, such as <dimen name="activity_margin">10dp</dimen> or whatever.
It is a good practice indeed to have all your hardcoded values (strings, dimens, colors, etc) on your XML resources, you just need to give them significant names (treat them as variable names).
Edit:
4) Add that method into your BaseActivity and pass the Toolbar as a param:
private void setupToolbar(Toolbar mainToolbar){
setSupportActionBar(mainToolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
}
Then, you can call it from your MainActivity as:
Toolbar mainToolbar = findViewById(R.id.main_toolbar);
setupToolbar(mainToolbar);
1- How to get reference to the drawer:
If all activities have drawer in its xml, and with the same Id, then you can use findViewById in BaseActivity.
protected DrawerLayout drawerLayout;
protected void initNavDrawer() {
drawerLayout = findViewById(R.id.drawer);
}
The BaseActivity is actually the current running activity, So findViewById is totally fine but make sure you have the drawer in all activity, else you will face NullPointerException
2- For starting activity, In each activity I add a static method which opens the activity
public static void openForEdit(#NonNull Activity context, #NonNull Order order, int requestCode) {
Intent editOrderIntent = new Intent(context, EditOrderActivity.class);
editOrderIntent.putExtra(ORDER_TAG, order);
editOrderIntent.putExtra(EDIT_TAG, true);
context.startActivityForResult(editOrderIntent, requestCode);
}
You can make more than one method if needed.
Then wherever you want to open the activity just call the static method
MyActivity.open(//passing parameters);
3- About the third point I didn't get exactly your point, But just for clarification: You need to create new xml file called dimens.xml, then you declare your dimens
4- You can put this method in BaseActivity and call it from onCreate in BaseActivity

Updating listview fragment on viewpager tab changes

I have a ViewPager using a FragmentPagerAdapter for displaying three tabs, each represented by its ow fragment. One of these fragments contains a list, that should be updated on switching / swiping to that tab. But I don't find any way to make it happen. I tried using the onResume method, but the fragments seem not to be paused and resumed on tab change. I also tried using ViewPager.OnPageChangeListener in my MainActivity:
#Override
public void onPageSelected(int position)
{
FragmentRefreshInterface currentFragment = (FragmentRefreshInterface) mSectionsPagerAdapter.getItem(position);
currentFragment.onRefreshed();
}
And in the fragment I use the following:
#Override
public void onRefreshed()
{
List<Record> records = mRecordingService.getRecords();
mRecordAdapter.clear();
mRecordAdapter.add(record);
}
But using this code I can't access my RecordingService class that is used to provide the database functions (because mRecordingService seems to be null). I initialize it in the fragment like this:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mRecordingService = new RecordingService(getContext());
}
Using the onPageChangeListener is the correct way to do it. I believe the reason why your code is not working, is because you are calling getItem on your pager adapter: getItem() actually returns a new instance of the fragment. In order to get the current instance, you use instantiateItem() (which returns a reference to the fragment actually being used).
Change your code to look something like this:
#Override
public void onPageSelected(int position)
{
FragmentRefreshInterface currentFragment = (FragmentRefreshInterface) mSectionsPagerAdapter.instantiateItem(viewPager,position);
currentFragment.onRefreshed();
}
And it should work.
I suggest that the code you have in onRefreshed() go in onResume() instead. Fragment doesn't have an onRefreshed() method. You must be implementing another interface that declares this method.
Since you are storing data in a database, you should be use a CursorAdapter or subclass such as SimpleCursorAdapter. If you do this correctly, the ListView will automatically update when you add a record to the database. Then the service can add records without needing to access the service from the fragment.
In your MainActivity:
private FirstFragment firstFragment;
private WantedFragment wantedFragment;
private ThirdFragment thirdfragment;
In getItem
switch(postition){
//return first, wanted, third fragments depending on position
}
onPageSelected:
if(position == 1) // position of the wanted fragment
wantedfragment.onRefreshed()

Different Colored Statusbar in each fragment

How can I define a different Statusbar and Actionbar color for each fragment ?
At the moment.
How it should look.
First of all, I would highly recommend you to migrate to new approach - Toolbar. It is much more flexible and you can customize it as plain View.
About your question.
You can just get ActionBar object and setBackground programatically.
Here is short example
ActionBar bar = getActionBar();
bar.setBackgroundDrawable(new ColorDrawable("COLOR IN HEX 0xFFFF6666 for instance"));
I will show how would I implement this. This is more about architecture and patterns.
Use some base class for Fragment it would be better to have base class for Activity as well. Lets consider
public class BaseFragment extends Fragment
And you Activity class in which your fragment lives.
public class MainActivity extends Activity
And you have to define responsibilities of Activity in this case and create interfaces
In your case to work with ActionBar
Create interface
public interface ActionBarProvider {
void setActionBarColor(ColorDrawable color);
}
Make your activity implement this interface
public class MainActivity extends Activity implements ActionBarProvider {
public void setActionBarColo(ColorDrawable color) {
ActionBar bar = getActionBar();
bar.setBackgroundDrawable(color));
}
}
And finally in BaseFragment in onAttach
public void onAttach(Context context) {
super.onAttach(context);
mActionBarProvider = (ActionBarProvider) context;
}
Make mActionBarProvider variable protected and make each fragment extend BaseFragment and you can change action bar color from any fragment like this mActionBarProvider.setActionBarColor(new ColorDrawable());
Hope this helps.

Android onChangeListener

Could somebody help me to create my own Listener.
I have an Activity where a String is changing and in an Activity's fragment I have to set a TextView's text for this String.
Why you are using Activity and Activity fragment?
just use fragment and make an interface
public interface ddd
{
void MyTestInterface(String str);
}
make your activityFragment implement it and than just pass your activity (this) to the other fragment how handle the string changes.
like: MyTestInterface.stringCallback("str")

android. How to conserve memory with custom ArrayAdapters and ViewPagers

So I have a MainActivity with a View Pager. I create a nonstatic custom FragmentPageAdapter for the View Pager like this:
public class CustomViewPageAdapter extends FragmentStatePagerAdapter {
The Adapter has 4 items(fragments) Which I declare as global variables MainActivity as static so for example:
static HotFragment hotFragment;
Then I return hotFragment in my getItem() method of the FragmentStatePagerAdapter.
Then in my HotFragment class I have another ViewPager as well as another FragmentStatePagerAdapter which is ALSO nonstatic: In the getItem() method of that Adapter return a new instance of another fragment called ImageDetailFragment like this:
return ImageDetailFragment.newInstance(arg0);
That ImageDetailFragment contatins an ImageView that will hold a different image depending on the value of arg0. That ImageView is loaded in an AsyncTask which is in the MainActivity. The async holds a WeakReference to the ImageView to ensure that it is Garbage collected.
My Problem is:
I am often getting and OutOfMemory error when I scroll through the images, especially when I exit the activity and then re enter the activity. I am very new to memory management and garbage collection but I think I have a memory leak somewhere. No this isn't a vague question however. What I want to know is:
Should I make my hotFragment static or not because I know static objects can cause memory leaks.
Also. My FragmentStatePagerAdapters are nonStatic is this bad. Should all Adapters be static in fragments.
Another thing. In my getItem(id) method in the FragmentPagerAdapter in my HotFragment I return:
ImageDetailFragment.newInstance();
instead of creating an instance of ImageDetailFragment in the actual HotFragment. Is this bad? Because in my MainActivity I don't return the hotFragment the same way I create a static instance of the hotFragment in the MainActivity then return that. Which one is better.
I would really appreciate it if you guys helped me. I am new to memory management and am unsure about what are the best practices to avoid memory leaks. I'm sorry if my question is too long or vague. I really tried to make it as descriptive as possible... Thank you
If you are really sure that having lots of static fragments in memory consumes a huge amount of memory, maybe you could try something like this:
Instead of using:
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position);
}
You could actually declare a Map of fragment. The main goal is to re-use previously created fragments, than keep declaring new instance. Firstly, declare this code on fragment's activity (NOT in SectionsPagerAdapter):
private Map<Integer, PlaceholderFragment> mPlaceHolderFragmentArray = new LinkedHashMap<Integer, PlaceholderFragment>();
Then replace getItem(int position) method in SectionsPagerAdapter with this:
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
PlaceholderFragment fragment = mPlaceHolderFragmentArray.get(position);
if(fragment == null){
fragment = PlaceholderFragment.newInstance(position);
mPlaceHolderFragmentArray.put(position, fragment);
}
return fragment;
}
I don't know if there are any better way, but I'm currently using this on my codes.

Categories

Resources