I'm making an authenticator following the tutorial: http://blog.udinic.com/2013/04/24/write-your-own-android-authenticator/
The login Activity requires to extend AccountAuthenticatorActivity, the issue starts here: AccountAuthenticatorActivity extends the regular Activity and not AppCompatActivity.
Using the regular Activity in AppCompat results in a Activity without ActionBar. I want to use AccountAuthenticatorActivity AND having an ActionBar.
I think that is not the real solution. If you are doing an app with support libraries, mixing AppCompatActivities, Fragments &c with the standard ones is not a good idea.
I´ve created an AccountAuthenticatorAppCompatActivity extending AppCompatActivity and then copy/paste the code from API AccountAuthenticatorActivity and it seems to work properly.
public class AccountAuthenticatorAppCompatActivity extends AppCompatActivity {
private AccountAuthenticatorResponse mAccountAuthenticatorResponse = null;
private Bundle mResultBundle = null;
public final void setAccountAuthenticatorResult(Bundle result) {
mResultBundle = result;
}
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mAccountAuthenticatorResponse =
getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
if (mAccountAuthenticatorResponse != null) {
mAccountAuthenticatorResponse.onRequestContinued();
}
}
public void finish() {
if (mAccountAuthenticatorResponse != null) {
// send the result bundle back if set, otherwise send an error.
if (mResultBundle != null) {
mAccountAuthenticatorResponse.onResult(mResultBundle);
} else {
mAccountAuthenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED,
"canceled");
}
mAccountAuthenticatorResponse = null;
}
super.finish();
}
}
Hope it helps to someone.
The key is AppCompatDelegate, my code is based on the AppCompatPreferenceActivity class generated by Android Studio:
#SuppressWarnings("unused")
public class AppCompatAuthActivity extends AccountAuthenticatorActivity {
private AppCompatDelegate mDelegate;
#Override
protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(#Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
#Override
#NonNull
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
#Override
public void setContentView(#LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
#Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
#Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
#Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
#Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
#Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
#Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}
The AppCompatDelegate is the key to add ActionBar to ANY regular Activity (for example PreferenceActivity).
Don't forget your activity must extend AppCompatAuthActivity.
Related
Hello i am trying to implement a log in screen showing a progress dialog and allowing the phone to rotate.
I want to ask what is the best way to do that (IntentService, AsyncTask,Service) and allowing the phone to rotate?
I read a lot answers saying different things using an empty fragment with AsyncTask etc.
You can do something like that in manifest to allow rotation:
<application
android:allowBackup="true"
android:configChanges="orientation|keyboardHidden|screenSize"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".activities.MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name"/>
Then you can catch the rotation with this snipet inside your activity:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.v(this.getClass().getName(), "onConfigurationChanged()");
}
To do an asynctask with progress dialog, this snipet should give you a ligth:
private ProgressDialog pDialog;
private class MyAsync extends AsyncTask<String, Void, String> {
Activity context;
public MyAsync (Activity context) {
this.context = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
pdia = new ProgressDialog(context);
pdia.setMessage("Loading...");
pdia.show();
}
#Override
protected String doInBackground(String... urls) {
...
//do your login scheme
...
//context.methods()
return "ok";
}
#Override
protected void onPostExecute(String result) {
pDialog.dismiss();
if(result!=null && result.equals("ok")){
//login was successfully done
} else {
//login has failed
}
}
}
And to use this asynctask you shoud call:
new MyAsync(this).execute(null, null , null);
By the way this is your activity/fragment.
Try adding this attribute android:configChanges="orientation" to your Activity element in the AndroidManifest.xml file.
show a ProgressDialog in the onPreExecute method of an AsyncTask object and canceling the ProgressDialog in the onPostExecute method. doInBackground method is running When change the orientation.
Refer to http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html for a detailed answer.
Basically, you can use fragment with setRetainInstance set to true inside your LoginActivity so that it doesn't get destroyed when activity is recreated during orientation change.
Sample Code :
public class AsyncFragment extends Fragment {
private LoginTask mTask;
private AsyncTaskListener mListener;
private static final String TAG = "AsyncFragment";
private boolean isTaskRunning = false;
private ProgressDialog mProgressDialog;
FrameLayout mLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mTask = new LoginTask();
mTask.execute();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mLayout = new FrameLayout(getActivity());
mLayout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
if(isTaskRunning) {
mProgressDialog = new ProgressDialog(getActivity());
mProgressDialog.show();
}
return mLayout;
}
#Override
public void onDestroyView() {
if(mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
super.onDestroyView();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mListener = (AsyncTaskListener) context;
} catch (ClassCastException e) {
Log.d(TAG, "Class not instance of AsyncTaskListener");
}
}
#Override
public void onDetach() {
mListener = null;
super.onDetach();
}
private class LoginTask extends AsyncTask<Void,Integer,Void> {
#Override
protected Void doInBackground(Void... params) {
if(mListener != null) {
mListener.onBackground();
}
SystemClock.sleep(10000);
return null;
}
#Override
protected void onPreExecute() {
isTaskRunning = true;
mProgressDialog = new ProgressDialog(getActivity());
mProgressDialog.show();
if(mListener != null) {
mListener.onPreExecute();
}
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mListener != null) {
mListener.onPostExecute();
}
isTaskRunning = false;
if(mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(mListener != null) {
mListener.onProgressUpdate(values[0]);
}
}
#Override
protected void onCancelled() {
super.onCancelled();
if(mListener != null) {
mListener.onCancelled();
}
}
}
//Listener to notify for async task callbacks
public interface AsyncTaskListener{
void onPreExecute();
void onPostExecute();
void onCancelled();
void onBackground();
void onProgressUpdate(int progress);
}
}
LoginActivity
public class MainActivity extends AppCompatActivity implements AsyncFragment.AsyncTaskListener{
private static final String FRAGMENT_TAG = "asyncFragment";
private static final String TAG = "MainActivity";
private AsyncFragment mAsyncFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm = getSupportFragmentManager();
mAsyncFragment = (AsyncFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (mAsyncFragment == null) { //fragment was retained during orientation change
mAsyncFragment = new AsyncFragment();
fm.beginTransaction().add(mAsyncFragment, FRAGMENT_TAG).commit();
}
}
#Override
public void onPreExecute() {
Log.d(TAG, "onPreExecute: ");
}
#Override
public void onPostExecute() {
Log.d(TAG, "onPostExecute: ");
}
#Override
public void onCancelled() {
Log.d(TAG, "onCancelled: ");
}
#Override
public void onBackground() {
Log.d(TAG, "onBackground: ");
}
#Override
public void onProgressUpdate(int progress) {
Log.d(TAG, "onProgressUpdate: ");
}
Have you tried this?
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize">
</activity>
This way the activity will not be recreated. but you can detect the screen orientation using onConfigurationChanged()
I have parent fragment called OpFragment. From this fragment are inherited all fragments in my app.
public abstract class OpFragment extends Fragment {
private Loading loading;
public abstract int getLayoutId();
public abstract void getData();
public abstract void setListeners();
protected BackHandlerInterface backHandlerInterface;
public boolean onBackPressed(){
return false;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
if(!(getActivity() instanceof BackHandlerInterface)) {
throw new ClassCastException("Hosting activity must implement BackHandlerInterface");
} else {
backHandlerInterface = (BackHandlerInterface) getActivity();
}
FragmentArgs.inject(this);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(getLayoutId(), container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if(!isAdded()){
return;
}
getData();
setListeners();
}
protected String returnName() {
return null;
}
public void showTitle() {
EventBus.getDefault().post(new ShowName(returnName()));
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
public Loading getLoading() {
if (this.loading == null) {
this.loading = new Loading(this.getActivity());
}
return this.loading;
}
/**
* Gets a component for dependency injection by its type.
*/
#SuppressWarnings("unchecked")
protected <C> C getComponent(Class<C> componentType) {
return componentType.cast(((HasComponent<C>) getActivity()).getComponent());
}
#Override
public void onStart() {
super.onStart();
backHandlerInterface.setSelectedFragment(this);
}
public interface BackHandlerInterface {
void setSelectedFragment(OpFragment backHandledFragment);
}
#Override
public void onResume() {
super.onResume();
sendGAScreens();
}
private void sendGAScreens() {
final Tracker tracker = OpApp.getDefaultTracker();
if(tracker != null) {
tracker.setScreenName(getClass().getSimpleName());
tracker.send(new HitBuilders.ScreenViewBuilder().build());
}
}
}
There are methods getData() and setListeners() inside onViewCreated.
I don't want to recall this methods after screen rotation. How can I do that ?
Simply checking savedInstanceState == null not gave me expected result.
override this method to detect screen rotation in your fragment and set some flag if its screen rotation. as shown below:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
Log.d("tag", "config changed");
super.onConfigurationChanged(newConfig);
int orientation = newConfig.orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT || orientation == Configuration.ORIENTATION_LANDSCAPE)
flag= true;
....
}
and in your onViewCreated() do like this
if(!flag){
// call your functions
}
I am trying to use Digits from Twitter.
The AuthCallBack is not fired when used from activity and the recent document saying to use the AuthCallBack from the Application class.
Now I have the AuthCallBack working correctly and onSuccess I need to call a method from my MainActivity. How do I achieve it from the Application class. Kindly help. I have given the code below.
public class MyApplication extends Application {
private AuthCallback authCallback;
#Override
public void onCreate() {
super.onCreate();
authCallback = new AuthCallback() {
#Override
public void success(DigitsSession session, String phoneNumber) {
//call myFunction() from MainActivity here
}
#Override
public void failure(DigitsException exception) {
}
};
}
public AuthCallback getAuthCallback(){
return authCallback;
}
}
You can use BroadcastManager to archive the same.
Below is sample code you can use
From Application:
#Override
public void success(DigitsSession session, String phoneNumber) {
Intent intent = new Intent(Constants.FILTER_LOGIN_SUCCESS);
intent.putExtra(Constants.EXTRA_PHONE_NUMBER, phoneNumber);
LocalBroadcastManager.getInstance(mInstance).sendBroadcast(intent);
}
Activity Class :
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(SignUpActivity.this).registerReceiver(broadcastReceiver,
new IntentFilter(Constants.FILTER_LOGIN_SUCCESS));
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(SignUpActivity.this).unregisterReceiver(broadcastReceiver);
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String phoneNumber = intent.getStringExtra(Constants.EXTRA_PHONE_NUMBER);
navigateToAnotherActivty();
}
};
Using interface you can achieve this
Write an interface something like this
public interface onSuccessListner {
void onSuccess(DigitsSession session,String phoneNumber);
}
Implement this interface in your Main Activity
public class MainActivity extends AppCompatActivity implements onSuccessListner{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onSuccess(DigitsSession session,String phoneNumber) {
//write your method calling or operations here
}
}
In your application class implement Application.ActivityLifecycleCallbacks to check main activity is created or not,If main activity created apply context of main activity to the listner
In on create inside your callback method call the success method of the MainActivity
public class MyApplctn extends Application implements Application.ActivityLifecycleCallbacks {
onSuccessListner onSuccessListner;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
authCallback = new AuthCallback() {
#Override
public void success(DigitsSession session, String phoneNumber) {
//call myFunction() from MainActivity here
if(onSuccessListner!=null){
onSuccessListner.onSuccess(session,phoneNumber);
}
}
#Override
public void failure(DigitsException exception) {
}
};
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (activity instanceof MainActivity) {
onSuccessListner= (com.mmadapps.myapplication.onSuccessListner) activity;
}
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
Hope this will help you
I have a SettingsActivity which extends PreferenceActivity to show settings in my app.
There is a back arrow, but it is not working.
Here's SettingsActivity.java file's code:
public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener{
private AppCompatDelegate mDelegate;
public static final String RESET_PASSWORD_KEY = "reset_password";
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
SharedPreferences sharedPreferencesCompat = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
Preference myPref = (Preference) findPreference(RESET_PASSWORD_KEY);
myPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
//open browser or intent here
Intent resetPasswordActivityIntent = new Intent(SettingsActivity.this, ResetPasswordActivity.class);
startActivity(resetPasswordActivityIntent);
return true;
}
});
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(#Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
getDelegate().getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
#Override
public void setContentView(#LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
#Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
#Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
#Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
#Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
#Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
#Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(RESET_PASSWORD_KEY)) {
}
}
}
Here's preferences.xml file's code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="xxx"
android:summary="xxxxxx"
android:key="reset_password" />
</PreferenceScreen>
Here's how 'SettingsActivity' is defined in AndroidManifest.xml:
<activity
android:name=".SettingsActivity"
android:label="#string/title_activity_settings"
android:parentActivityName=".MainActivity">
</activity>
How can I make that arrow operational?
Please let me know.
Sorry, if question format seems inappropriate. I'm still a beginner.
You need to call your private method setSupportActionBar() inside onCreate().
Also, you might want to implement onOptionsItemSelected:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
You can do it like this
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
I have made some assumptions on what you might be trying to achieve. This should work if you want to use a custom toolbar with PreferenceActivity. The following code goes inside onPostCreateView()
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
mToolBar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.toolbar, root,false);
mToolBar.setTitle(R.string.title);
// insert at top
root.addView(mToolBar, 0);
setSupportActionBar(mToolBar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
You forgot to call this method in your onCreate()
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
In Android targetSdkVersion 29
inside onCreate()
getActionBar().setDisplayHomeAsUpEnabled(true);
then implement onOptionsItemSelected from #Matias Elorriaga Answer
If all else fails, try calling setDisplayHomeAsUpEnabled() twice with different arguments:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
I'm experiencing an strange behavior of Fragment life-cycle each time that i rotate the screen. Only the first half of life-cycle methods are getting called, onPause,onSaveInstanceState,onStop, onDestroyView,onDestroy and onDetach. The other half (onAttach ...-onResume) are not getting called. The Activity associated with the Fragment is calling all its life-cycle methods.
Any help would be highly appreciated because I'm stuck on this issue.
Thanks in advance.
Here the entire code of the Activity and the static nested class where is the Fragment:
public class MoviesFeed extends AppCompatActivity {
private static boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("ACT","onCreate");
setContentView(R.layout.themoviedb_main);
if(findViewById(R.id.detail_activity_container)!=null) {
//the detail_activity_container will be present only in large-screen
//Layouts (res/Layout-sw600dp. If this view is present, then the activity
//should be in two-pane mode
mTwoPane=true;
//In two-pane mode, show the detail view in this activity by adding
// or replacing the detail fragment using a fragment transaction
DetailActivityFragment detailActivityFragment=new DetailActivityFragment();
// Bundle bundle=new Bundle();
// bundle.putBoolean("twopane",mTwoPane);
// detailActivityFragment.setArguments(bundle);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.detail_activity_container, detailActivityFragment)
.commit();
}
} else {
mTwoPane=false;
}
}
#Override
protected void onStart() {
Log.d("ACT","onStart");
super.onStart();
}
#Override
protected void onResume() {
Log.d("ACT","onResume");
super.onResume();
}
#Override
protected void onPause() {
Log.d("ACT","onPause");
super.onPause();
}
#Override
protected void onStop() {
Log.d("ACT","onStop");
super.onStop();
}
#Override
protected void onRestart() {
Log.d("ACT","onRestart");
super.onRestart();
}
#Override
protected void onDestroy() {
Log.d("ACT","onDestroy");
super.onDestroy();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.movies_feed_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
startActivity(new Intent(this,SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
public static class MoviesFeedFragment extends Fragment implements AdapterView.OnItemClickListener {
private static final int APPROX_FIXED_IMAGE_WIDTH=170;
private GridView mGridView;
private MovieAdapter mMovieAdapter;
private ArrayList<Response.Movie> mListMovies=new ArrayList<Response.Movie>();
private TimeMeasure mTm;
private boolean mFromDetailsActivity =false;
private boolean mUserRotation=false;
private boolean mFavoritesMode=false;
#Override
public void onAttach(Activity activity) {
Log.d("FRAG", "onAttach");
super.onAttach(activity);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FRAG", "onCreate");
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_moviesfeed, container, false);
Log.d("FRAG", "onCreateView");
mGridView= (GridView) view.findViewById(R.id.gridView);
mGridView.setOnItemClickListener(this);
mMovieAdapter = new MovieAdapter(getActivity(), mListMovies);
mGridView.setAdapter(mMovieAdapter);
//for tablets specially
// float scalefactor = getResources().getDisplayMetrics().density * APPROX_FIXED_IMAGE_WIDTH;
// Point size=new Point();
// getWindowManager().getDefaultDisplay().getSize(size);
// int number=size.x;
// int columns = (int) ((float) number / (float) scalefactor);
//
// mGridView.setNumColumns(columns);
if(savedInstanceState!=null){
mUserRotation=true;
ArrayList<Response.Movie> tempList=new ArrayList<Response.Movie>();
tempList=savedInstanceState.getParcelableArrayList("mListMovies");
mListMovies.clear();
mListMovies.addAll(tempList);
mMovieAdapter = new MovieAdapter(getActivity(), mListMovies);
mGridView.setAdapter(mMovieAdapter);
}
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
Log.d("FRAG", "onActivity");
super.onActivityCreated(savedInstanceState);
}
#Override
public void onPause() {
Log.d("FRAG", "onPause");
super.onPause();
}
#Override
public void onStop() {
Log.d("FRAG", "onStop");
super.onStop();
}
#Override
public void onSaveInstanceState(Bundle outState) {
Log.d("FRAG", "onSaveInstanceState");
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("mListMovies", mListMovies);
}
#Override
public void onResume() {
Log.d("FRAG", "onResume");
super.onResume();
if (mFromDetailsActivity !=true && mUserRotation!=true) {
executeCallToMoviesApi();
} else if(mFromDetailsActivity==true && mFavoritesMode==true) {
getFavoritesMovies();
}
mFromDetailsActivity =false;
mUserRotation=false;
}
#Override
public void onDestroyView() {
Log.d("FRAG", "onDestroyView");
super.onDestroyView();
}
#Override
public void onDestroy() {
Log.d("FRAG", "onDestroy");
super.onDestroy();
}
#Override
public void onDetach() {
Log.d("FRAG", "onDetach");
super.onDetach();
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mTwoPane==true) {
DetailActivityFragment detailActivityFragment=new DetailActivityFragment();
Bundle args=new Bundle();
args.putString("movieId", String.valueOf(mListMovies.get(position).getId()));
//Response.Movie movie=new Response.Movie();
//movie.setId(mListMovies.get(position).getId());
//args.putParcelable("movie",movie);
args.putBoolean("favoritesMode",mFavoritesMode);
detailActivityFragment.setArguments(args);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.detail_activity_container,detailActivityFragment)
.commit();
} else {
Intent intent = new Intent(getActivity(), DetailActivity.class);
intent.putExtra("favoritesMode", mFavoritesMode);
intent.putExtra("movieId", mListMovies.get(position).getId());
mFromDetailsActivity = true;
startActivity(intent);
}
}
public void executeCallToMoviesApi(){
SharedPreferences sharedPreferences= PreferenceManager.getDefaultSharedPreferences(getActivity());
String orderStr= sharedPreferences.getString(getString(R.string.pref_order_key),
getString(R.string.pref_order_default));
mFavoritesMode=false;
if (orderStr.equals(getString(R.string.pref_popularity))){
getActivity().setTitle(getString(R.string.mainactivity_title_popularity));
getMoviesByPopularity();
}
if (orderStr.equals(getString(R.string.pref_rate))){
getActivity().setTitle(getString(R.string.mainactivity_title_rate));
getMoviesByRate();
}
if (orderStr.equals(getString(R.string.pref_favorites))) {
getActivity().setTitle(getString(R.string.mainactivity_title_favorites));
mFavoritesMode=true;
getFavoritesMovies();
}
}
public void getMoviesByPopularity(){
ApiClient.MyApi myApi=ApiClient.getMyApiClient();
myApi.getMoviesByPopularityDesc(AppConstants.API_KEY, callbackResponse());
}
public void getMoviesByRate(){
ApiClient.MyApi myApi=ApiClient.getMyApiClient();
myApi.getMoviesByAverageRate(AppConstants.API_KEY, callbackResponse());
}
private Callback<Response> callbackResponse() {
return new Callback<Response>() {
#Override
public void success(Response response, retrofit.client.Response response2) {
// Message.displayToast(MoviesFeed.this, "success");
mListMovies.clear();
mListMovies.addAll((ArrayList) response.getResults());
mMovieAdapter = new MovieAdapter(getActivity(), mListMovies);
mGridView.setAdapter(mMovieAdapter);
}
#Override
public void failure(RetrofitError error) {
Log.v("VILLANUEVA", "error:" + error.getMessage().toString());
Message.displayToast(getActivity(), "failure" + error.getMessage().toString());
}
};
}
public void getFavoritesMovies(){
List<MovieDetail> tempListDetail;
ArrayList<Response.Movie> tempList=new ArrayList<Response.Movie>();
SharedPreferenceManager sharedPreferenceManager=new SharedPreferenceManager(getActivity());
tempListDetail = sharedPreferenceManager.getFavoritesList();
Response.Movie tempMovie;
if (tempListDetail!=null) {
for (MovieDetail movieDetail : tempListDetail) {
tempMovie = new Response.Movie();
tempMovie.setId(movieDetail.getId());
tempMovie.setPoster_path(movieDetail.getPoster_path());
tempList.add(tempMovie);
}
mListMovies.clear();
mListMovies.addAll(tempList);
}
mMovieAdapter = new MovieAdapter(getActivity(), mListMovies);
mGridView.setAdapter(mMovieAdapter);
}
}//MoviesFeedFragment
Screenshots, before and after rotation.
Before:
After:
Log