Custom Dialog not cancelling even after setting cancellable true - java

I have a custom ActivityIndicator defined as this
public class ActivityIndicator extends Dialog
{
private ImageView progress;
private ImageView bottomProgress;
private int type = INDICATOR_SIMPLE;
public static final int INDICATOR_SIMPLE = 0;
public static final int INDICATOR_BOTTOM = 1;
public ActivityIndicator(Context context, int theme, int type)
{
super(context, theme);
this.type = type;
onCreate(null);
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_indicator);
progress = (ImageView) findViewById(R.id.progress);
bottomProgress = (ImageView) findViewById(R.id.bottomProgress);
if(type == INDICATOR_BOTTOM)
{
progress.setVisibility(View.INVISIBLE);
}
else if(type == INDICATOR_SIMPLE)
{
bottomProgress.setVisibility(View.INVISIBLE);
}
this.setCancelable(false);
}
#Override
public void show()
{
progress.clearAnimation();
bottomProgress.clearAnimation();
if(type == INDICATOR_BOTTOM)
{
progress.setVisibility(View.INVISIBLE);
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
Animation anim = AnimationUtils.loadAnimation(getContext(), R.anim.rotating_img);
bottomProgress.startAnimation(anim);
}
},400);
}
if(type == INDICATOR_SIMPLE)
{
bottomProgress.setVisibility(View.INVISIBLE);
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
Animation anim = AnimationUtils.loadAnimation(getContext(), R.anim.rotating_img);
progress.startAnimation(anim);
}
},400);
}
super.show();
}
#Override
public void dismiss()
{
super.dismiss();
progress.clearAnimation();
bottomProgress.clearAnimation();
}
}
In my activity I initialize it as:
indicator = new ActivityIndicator(this, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen, ActivityIndicator.INDICATOR_SIMPLE);
Now as seen in code , default style cancelable is false.
However at some point i do want to put it cancelable , here is my code:
indicator.setCancelable(true);
indicator.setOnCancelListener(new DialogInterface.OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
finish();
}
});
indicator.show();
When I try to press the back button, nothing happens, the dialog doesn't cancel nor the cancel listener. What is wrong here? Why is it not cancelling automatically on back key pressed

Don't Override onCreate(). That onCreate(null) method that you invoke is what's screwing up your code. Rather use an initializer pattern to initialize the Dialog.
If you change your onCreate to an initialize() and invoke that from the constructor the code will work.
Look at the following.
public ActivityIndicator(Context context, int theme, int type)
{
super(context, theme);
this.type = type;
initialize();
}
protected void initialize()
{
setContentView(R.layout.dialog_indicator);
setCancelable(false);
progress = (ImageView) findViewById(R.id.progress);
bottomProgress = (ImageView) findViewById(R.id.bottomProgress);
if(type == INDICATOR_BOTTOM)
{
progress.setVisibility(View.INVISIBLE);
}
else if(type == INDICATOR_SIMPLE)
{
bottomProgress.setVisibility(View.INVISIBLE);
}
}

Please comment your seton cancellabel and use below code and check.
indicator.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
finish();
}
}
}

When you are creating an instance of ActivityIndicator, in the OnCreate method, setCancelable is set to false.
Try removing that..

Got you problem just change your constructor like below and you would get your cancel listner called:
public ActivityIndicator(Context context, int theme, int type, boolean isCancelable)
{
super(context, theme);
this.type = type;
onCreate(null);
this.setCancelable(isCancelable); //setcancelable here on the basis of boolean value and remove setcancelable from onCreate()
}
Call the constructor with one more argument which is boolean true/false
Note: Don't forget to remove setCancelable() from onCreate() method.

Related

How to continuously increment multiple RecyclerView values in parallel

Context
Working with RecyclerView items that each have label and value TextViews, and a start Button.
Goals
to start and continue incrementing a value when its start Button is pressed
must be possible to individually start each item's value via its Button
once started, multiple values must be able continuously increment in parallel
Problem
UI (value TextView, clicking Button, etc.) slows down after 2 or more values start incrementing. Unsure how to handle threading (tried HandlerThread/runOnUiThread, currently using individual thread for each MyValue object), see MyValue.start() in Code below.
How can individual values be continously incremented in parallel while updating RecyclerView without slowing UI?
What's been tried so far
Using HandlerThread and runOnUiThread
Using individual Thread for each MyValue object
Considered AsyncTask but in the future it is likely that "incrementing multiple values" behaviour will need to run in the background independent of the Activity (i.e., only updating GUI when Activity is in foreground), hence the behaviour may move to a BoundService
It may be possible to use LiveData to have RecyclerView items observe and update based on the value in MyValue, however, unsure how LiveData can work with MyValue and ValuesAdapter
Code
MainActivity
public class MainActivity extends AppCompatActivity {
ArrayList<MyValue> mValues;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
mValues = new ArrayList<>();
mValues.add(new MyValue("value 1"));
mValues.add(new MyValue("value 2"));
mValues.add(new MyValue("value 3"));
ValuesAdapter valuesAdapter = new ValuesAdapter(mValues);
recyclerView.setAdapter(valuesAdapter);
}
}
ValuesAdapter
public class ValuesAdapter extends RecyclerView.Adapter<ValuesAdapter.ValueViewHolder> {
private List<MyValue> mValues;
private Context mContext;
private ValueController mValueController;
public ValuesAdapter(List<MyValue> values) {
mValues = values;
mValueController = new ValueController(mValues);
}
#Override
public ValueViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mContext == null) {
mContext = parent.getContext();
}
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View valueView = layoutInflater.inflate(R.layout.value_item, parent, false);
return new ValueViewHolder(valueView);
}
#Override
public void onBindViewHolder(ValueViewHolder holder, int position) {
MyValue value = mValues.get(position);
String label = value.getLabel();
int currentValue = value.getValue();
holder.setupViewHolder(label, "" + currentValue);
value.setListener(holder);
}
#Override
public int getItemCount() {
return mValues.size();
}
class ValueViewHolder extends RecyclerView.ViewHolder
implements MyValue.ValueListener {
TextView mLabel;
TextView mValue;
Button mStart;
public ValueViewHolder(View itemView) {
super(itemView);
mLabel = itemView.findViewById(R.id.label);
mValue = itemView.findViewById(R.id.value);
mStart = itemView.findViewById(R.id.start);
}
public void setupViewHolder(String label, String currentValue) {
mLabel.setText(label);
mValue.setText(currentValue);
int adapterPosition = getAdapterPosition();
final MyValue value = mValues.get(adapterPosition);
mStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
value.start();
}
});
}
#Override
public void onTick(final int currentValue) {
mValueController.incActiveStopwatches();
((Activity) mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
mValue.setText("" + currentValue);
}
});
}
}
}
ValueController
public class ValueController {
private List<MyValue> mValues;
public ValueController(List<MyValue> values) {
mValues = values;
}
public void incrementActiveValues() {
for (int i = 0; i < mValues.size(); i++) {
MyValue value = mValues.get(i);
if (value.getShouldIncrement()) {
value.increment();
}
}
}
}
MyValue
public class MyValue {
private String mLabel;
private int mCurrentValue;
private boolean mShouldIncrement;
private Handler mHandler;
private ValueListener mListener;
public MyValue(String label) {
mLabel = label;
HandlerThread handlerThread = new HandlerThread("HandlerThread1");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
}
public String getLabel() {
return mLabel;
}
public int getValue() {
return mCurrentValue;
}
public void increment() {
mCurrentValue++;
}
public void start() {
mShouldIncrement = true;
new Thread(new Runnable() {
#Override
public void run() {
while (mShouldIncrement) {
increment();
if (mListener != null) {
mListener.onTick(mCurrentValue);
}
}
}
}).start();
// mHandler.post(new Runnable() {
// #Override
// public void run() {
// while (mShouldIncrement) {
// increment();
// if (mListener != null) {
// mListener.onTick(mCurrentValue);
// }
// }
// }
// });
}
public void setListener(ValueListener listener) {
mListener = listener;
}
public interface ValueListener {
void onTick(int currentValue);
}
public boolean getShouldIncrement() {
return mShouldIncrement;
}
}
Problem
Seems a high frequency of work (i.e., skipping around 2000 frames when incrementing value and updating RecyclerView TextView value) was done via MyValue.ValueListener.onTick().
Solution
Current solution was delay onTick to only fire every 1 second, i.e., replace MyValue.start() with this:
private Runnable mRepeatIncrementRunnable = new Runnable() {
#Override
public void run() {
if (mShouldIncrement) {
increment();
if (mListener != null) {
mListener.onTick(mCurrentValue);
}
} else {
mHandler.removeCallbacks(this);
return;
}
mHandler.postDelayed(this, mTickIntervalMs);
}
};
public void start() {
mShouldIncrement = true;
mHandler.post(mRepeatIncrementRunnable);
}

Android recycler view toggle button recycling issue

I am making an app and has a recyclerview for showing user feed. I am using a toggle button for liking posts. When the user opens the app it enables the like button if the status is already liked by the user who is using the app and the user can also like the posts by scrolling down like other socials apps out there.
The problem is if a toggle button is checked when scrolling down
other toggle buttons belongs to other posts are also getting checked.
Adapter class
public class topNewsAdapter extends RecyclerView.Adapter<topNewsRowHolder> {
private ArrayList<topData> topDataList;
private Context context;
private Activity activity;
private RecyclerView recyclerView;
private View v;
protected String liked = "success";
protected String expired = "Expired";
public topNewsAdapter( ArrayList<topData> listItemList , Activity activity , RecyclerView view) {
this.topDataList = listItemList;
this.activity = activity;
this.recyclerView = view;
}
#Override
public topNewsRowHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.top_news_row, parent, false);
context = parent.getContext();
return new topNewsRowHolder(v , activity); //passed activity
}
#Override
public void onBindViewHolder(final topNewsRowHolder holder, final int position) {
topData item = topDataList.get(position);
if(!(item == null)) {
holder.userName.setText(item.getUserName().toString());
holder.timer.setText(item.getCreatedTime().toString());
holder.status.setText(item.getStatus().toString());
holder.fameCount.setText(item.getLikeCount().toString());
holder.dislike_Count.setText(item.getDislike_Count().toString());
holder.statusID.setText(item.getStatusID().toString());
if(item.getLiked().equals(1)){
holder.fameButton.setChecked(true);
}else if(item.getLiked().equals(0)){
holder.fameButton.setChecked(false);
}
if(item.getDisliked().equals(1)){
holder.disLikeButton.setChecked(true);
}else if(item.getDisliked().equals(0)){
holder.disLikeButton.setChecked(false);
}
holder.fameButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
lRequester(holder.statusID.getText().toString() , "1" , holder.fameCount );
dRequester(holder.statusID.getText().toString() , "0" , holder.dislike_Count);
holder.fameButton.setChecked(true);
}else if(!isChecked){
lRequester(holder.statusID.getText().toString() , "0" , holder.fameCount);
}
}
});
holder.disLikeButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
dRequester(holder.statusID.getText().toString(), "1" ,holder.dislike_Count);
lRequester(holder.statusID.getText().toString() , "0" , holder.fameCount);
holder.fameButton.setChecked(false);
}else if(!isChecked){
dRequester(holder.statusID.getText().toString() , "0" , holder.dislike_Count);
}
}
});
}
}
#Override
public int getItemCount() {
return topDataList.size();
}
#Override
public long getItemId(int position) {
return position;
}
public void lRequester(String id , String type, final TextView textview){
Call<responseFD> request = handler.handlerClass.fame(data("u") , data("t") , id , type );
request.enqueue(new Callback<responseFD>() {
#Override
public void onResponse(Call<responseFD> call, Response<responseFD> response) {
if(!response.body().getResponse().isEmpty() && (response.body().getResponse() != null)) {
if (response.body().getResponse().equals(expired)) {
vlData.getInstance().terminateRunnable();
reset();
}else if (response.body().getResponse().equals(liked)) {
textview.setText(response.body().getLike_count().toString());
}
}
}
#Override
public void onFailure(Call<responseFD> call, Throwable t) {
Toast.makeText(v.getContext(), "Something Gone Wrong", Toast.LENGTH_SHORT).show();
}
});
}
public void dRequester(String id , String type , final TextView textView){
Call<responseFD> request = handler.handlerClass.disfame(data("u") , data("t") , id , type );
request.enqueue(new Callback<responseFD>() {
#Override
public void onResponse(Call<responseFD> call, Response<responseFD> response) {
if(!response.body().getResponse().isEmpty() && response.body().getResponse() != null) {
if (response.body().getResponse().equals(expired)) {
vlData.getInstance().terminateRunnable();
reset();
}else if (response.body().getResponse().equals(liked)) {
textView.setText(response.body().getDislike_Count().toString());
}
}
}
#Override
public void onFailure(Call<responseFD> call, Throwable t) {
Log.d("data", "onFailure: " + t.getMessage());
}
});
}
public void reset(){
Intent i = new Intent(activity , login.class);
activity.startActivity(i);
activity.finish();
}
}
Rowholder class
public class topNewsRowHolder extends RecyclerView.ViewHolder {
protected TextView userName;
protected TextView timer;
protected TextView status;
protected ImageView profilePicHolder;
protected TextView fameCount;
protected TextView dislike_Count;
protected ToggleButton fameButton;
protected ToggleButton disLikeButton;
protected View v;
protected TextView statusID;
protected Activity activity;
protected RelativeLayout holderlayout;
public topNewsRowHolder(View view , Activity activity ){
super(view);
v = view;
this.activity = activity;
this.userName = (TextView)view.findViewById(R.id.usernameHolder);
this.timer = (TextView)view.findViewById(R.id.timeHolder);
this.status = (TextView)view.findViewById(R.id.status_user);
this.profilePicHolder = (ImageView)view.findViewById(R.id.profile_pic_holder);
this.fameCount = (TextView)view.findViewById(R.id.like_count);
this.dislike_Count = (TextView)view.findViewById(R.id.dislike_count);
this.fameButton = (ToggleButton)view.findViewById(R.id.fameButton);
this.disLikeButton = (ToggleButton)view.findViewById(R.id.dislikeButton);
this.statusID = (TextView)view.findViewById(R.id.statusID);
this.holderlayout = (RelativeLayout) view.findViewById(R.id.text);
}
}
I know this is because of the recycling. How to fix this issue ?. Thanks :)
Try this : RecyclerView needs an external variable to keep track of which items are checked, while SparseBooleanArray will work, its tedious.
holder.fameButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean IsChecked) {
isChecked ? item.setIsLiked(1) : item.setIsLiked(0);
if(isChecked){
lRequester(holder.statusID.getText().toString() , "1" , holder.fameCount );
dRequester(holder.statusID.getText().toString() , "0" , holder.dislike_Count);
} else if(!isChecked){
lRequester(holder.statusID.getText().toString() , "0" , holder.fameCount);
}
}
});
Create a Broker pattern for managind likes within the content feed.
This singleton broken would keep track of each Content feed item id and map it to a state (social or just likes) in a hashmap. And every time there is a reaction (like/unlike/dislike/undislike) happenning to a Content feed item, you trigger the actian using this Broker that also propagates and keeps track of the changes locally. You ahould implement a Broadcaster or a pub-sub pattern to ibform the UI about the changes.
Preferably use a Content Provider with a database for storing the json you are getting from the webserver.
Let me know if you need further clarifications.
SocialBroker.java
public class SocialBroker extends ISocialBroker {
//region <!-- Private properties -->
private static SocialBroker _instance;
private HashMap<UUID, SocialStatus> _map = new HashMap<>();
//endregion
//region <!-- Singleton initializer -->
public static SocialBroker newInstance() {
if (_instance == null) {
_instance = new SocialBroker();
}
return _instance;
}
private SocialBroker() {};
//endregion
// The interface method implemented here
}
ISocialBroker.java
public interface ISocialBroker {
public synchronized SocialStatus save(String expiresAt, UUID id, boolean hasLiked, int numberOfLikes, int numberOfComments);
public SocialStatus lookup(UUID id);
public synchronized SocialStatus like(UUID id);
public synchronized SocialStatus unlike(UUID id);
public HashMap<UUID, SocialStatus> getMap();
public void loadState(HashMap<UUID, SocialStatus> restoredSocialState);
}
OnReactionObserver.java
public interface OnReactionObserver {
void onLikeReaction();
}
OnReactionPublisher.java
public interface OnReactionPublisher {
void attachObserver(OnReactionObserver... observer);
void notifyListeners();
}
When you bind the results to your views in your adapter, you save the entries using the broker, then in your like button view, you summon the Broker again to execute the like/unlike/dislike/undislike.
SocialStatus is just a model to keep track of information, that can be serialized, saved, synchronized with an online service.
Hope this points you to the right direction.

MediaPlayer won't stop playing even if programmed to

I made a simple class that handles everything related to sound. Has an add, play, stop, release and releaseAll. How it works is that you have to add a song and then call play passing the name of the song you added. Anytime you need to stop, just call the stop function and pass the song's name as parameter and it should stop. My issue is that it isn't stopping even though it goes through stop().
Sound class:
public class Sound
{
private Map<String, MediaPlayer> songs = new HashMap<String, MediaPlayer>();
private MediaPlayer currentlyPlayingSong;
public Sound() {}
public void Add(int songId, String songName, Context context)
{
MediaPlayer song = MediaPlayer.create(context, songId);
songs.put(songName, song);
}
public void Play(String name, boolean shouldLoop)
{
MediaPlayer songToPlay = songs.get(name);
if ( songToPlay != currentlyPlayingSong && songToPlay != null)
{
currentlyPlayingSong = songToPlay;
currentlyPlayingSong.start();
currentlyPlayingSong.setLooping(shouldLoop);
}
}
public void Stop(String name)
{
MediaPlayer songToStop = songs.get(name);
if (songToStop != null)
{
songToStop.setLooping(false);
songToStop.stop();
}
}
public void Release(String name)
{
songs.get(name).release();
}
public void ReleaseAll()
{
LinkedList<MediaPlayer> _songs;
_songs = (LinkedList)songs.values();
for (int i = 0; i < _songs.size(); i++)
{
_songs.get(i).release();
}
}
}
On the activity's OnCreate I call Add then Play. Everything is fine until I try to call Stop from a fragment. Runs without any errors or exceptions, it simply doesn't stop.
Activity:
public class Main extends ActionBarActivity
{
private Sound sound = new Sound();
private static boolean isSoundOn = true;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
isSoundOn = true;
sound.Add(R.raw.drajamainmenueddited, "mainMenuSong", this);
//endregion
//Hide upper action bar
getSupportActionBar().hide();
if (isSoundOn)
sound.Play("mainMenuSong", true);
}
public void SetIsSoundOn(Boolean isOn)
{
isSoundOn = isOn;
}
public boolean GetIsSoundOn()
{
return isSoundOn;
}
public Sound GetSoundObj()
{
return sound;
}
}
Fragment:
public class MainMenuFragment extends Fragment {
private ImageButton soundImgBtn;
private FragmentConfig fragmentConfig;
public MainMenuFragment()
{
fragmentConfig = new FragmentConfig();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
//region Initiators
View view = inflater.inflate(R.layout.fragment_main_menu, container, false);
soundImgBtn = (ImageButton)view.findViewById(R.id.soundImgBtn);
//endregion
//region Listeners
soundImgBtn.setOnClickListener(
new View.OnClickListener()
{
#Override
public void onClick(View v)
{
SoundImgBtnClick(v);
}
}
);
//endregion
//Changes audio img
if (((Main)getActivity()).GetIsSoundOn())
soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode_off);
else
soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode);
// Inflate the layout for this fragment
return view;
}
private void SoundImgBtnClick(View v)
{
//if sound is on and clicked, turn off
if (((Main)getActivity()).GetIsSoundOn())
{
((Main)getActivity()).SetIsSoundOn(false);
((Main)getActivity()).GetSoundObj().Stop("mainMenuSong");
soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode);
}
else
{
((Main)getActivity()).SetIsSoundOn(true);
((Main)getActivity()).GetSoundObj().Play("mainMenuSong", true);
soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode_off);
}
}
}
What I'm trying to do is emulate a mute button. Once clicked all sounds should be muted.
This is pretty much all I've coded, so far.
Cheers.
I suspect you're using different instances of MediaPlayer. You are allowed to do that BUT you must stop the song within the same instance.
About the code in Add():
MediaPlayer song = MediaPlayer.create(context, songId);
In Stop():
MediaPlayer songToStop = songs.get(name)
Note:
The above codes tell me you're using different instances of the MediaPlayer for one same song. The object song needs to be declared on a higher scope for you to access it and to stop the song.
Need to call release() method after stop() to free up resources.
try songToStop.release() instead
Got it to stop. My class had to be able to handle one song at a time and many fx at the same time. This is what I came up with.
Sound:
public class Sound
{
private static MediaPlayer currentlyPlayingSong,
currentlyPlayingFX;
public Sound() {}
public void PlayFX(int fxId, Context context, boolean shouldLoop)
{
MediaPlayer fx = MediaPlayer.create(context, fxId);
if (currentlyPlayingFX != fx)
{
StopFX();
currentlyPlayingFX = fx;
currentlyPlayingFX.start();
currentlyPlayingFX.setLooping(shouldLoop);
}
}
public void PlaySong(int songId, boolean shouldLoop, Context context)
{
MediaPlayer song = MediaPlayer.create(context, songId);
if (currentlyPlayingSong != song)
{
StopSong();
currentlyPlayingSong = song;
currentlyPlayingSong.start();
currentlyPlayingSong.setLooping(shouldLoop);
}
}
public void StopFX()
{
if (currentlyPlayingFX != null)
{
currentlyPlayingFX.stop();
currentlyPlayingFX.release();
currentlyPlayingFX = null;
}
}
public void StopSong()
{
if (currentlyPlayingSong != null)
{
currentlyPlayingSong.stop();
currentlyPlayingSong.release();
currentlyPlayingSong = null;
}
}
}
This is was based of what #The Original Android answered. Keep it on a single instance.
Thanks for the help.

Android - Ghost Views after Animations

In my SMS app, I have a dialog that opens when the user clicks on an attached image to expand it.
Everything worked fine until I decided to add animations. This dialog has 3 buttons (one close ImageButton in the top right corner and two buttons in a bottom bar of the dialog). When the user clicks on the image, the buttons anime out/in. This all works fine except the buttons are still clickable even after they're hidden.
Before Animations:
After Animations:
My code for the dialog below:
// Declare these here to increase scope. (Listeners)
private static boolean ContainerChanged;
private static boolean ActionsHidden;
private static boolean AnimStarted;
private static boolean closeAnimFinished;
private static boolean barAnimFinished;
private void showExpandedImageDialog(Uri imgUri)
{
// Initialize Dialog
final Dialog dialog = new Dialog(ActivitySend.this, R.style.FullHeightDialog);
dialog.setContentView(R.layout.dialog_attachment_image_send);
// Initialize Views
final RelativeLayout Container = (RelativeLayout) dialog.findViewById(R.id.Container);
final LinearLayout actions = (LinearLayout) dialog.findViewById(R.id.Actions);
final ImageButton btnClose = (ImageButton) dialog.findViewById(R.id.btnClose);
Button btnReplace = (Button) dialog.findViewById(R.id.btnReplace);
Button btnRemove = (Button) dialog.findViewById(R.id.btnRemove);
ImageView image = (ImageView) dialog.findViewById(R.id.Image);
// Load Image & Make Zoomable
PhotoViewAttacher mAttacher = new PhotoViewAttacher(image);
image.setImageURI(imgUri);
mAttacher.update();
// Get animations ready
final Animation fiCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_in);
fiCloseAnim.setFillEnabled(true);
fiCloseAnim.setFillAfter(true);
final Animation foCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_out);
foCloseAnim.setFillEnabled(true);
foCloseAnim.setFillAfter(true);
final Animation dBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_down);
dBarAnim.setFillEnabled(true);
dBarAnim.setFillAfter(true);
final Animation uBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_up);
uBarAnim.setFillEnabled(true);
uBarAnim.setFillAfter(true);
// Reset static variables
ActionsHidden = false;
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
// Initialize listeners
AnimationListener closeAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
closeAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
AnimationListener barAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
barAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
// Set listeners
fiCloseAnim.setAnimationListener(closeAnimListener);
foCloseAnim.setAnimationListener(closeAnimListener);
dBarAnim.setAnimationListener(barAnimListener);
uBarAnim.setAnimationListener(barAnimListener);
// Actions Appear/Disappear onTap (Animate)
mAttacher.setOnPhotoTapListener(new OnPhotoTapListener()
{
#Override
public void onPhotoTap(View view, float x, float y)
{
if (!AnimStarted && ActionsHidden)
{
actions.startAnimation(uBarAnim);
btnClose.startAnimation(fiCloseAnim);
}
else if (!AnimStarted)
{
actions.startAnimation(dBarAnim);
btnClose.startAnimation(foCloseAnim);
}
}
});
// Make dialog square
ContainerChanged = false;
ViewTreeObserver vto = Container.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
// Set boolean to save processing power
if (!ContainerChanged)
{
int width = Container.getMeasuredWidth();
Container.getLayoutParams().height = width;
ContainerChanged = true;
}
return true;
}
});
// Set button listeners
btnClose.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dialog.dismiss();
}
});
btnReplace.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
btnRemove.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
// Show dialog
dialog.show();
}
Everything works perfectly if I remove the animations and only use view.setVisibility(View.GONE) but I really like the animations...
Any ideas on what I could do to fix this?
I could probably use view.setClickable(false); but I'm sure there's a better solution than that.
You can do it like this:
Let your activity implement AnimationListener. Then there will be an overridden method public void onAnimationEnd(Animation arg0), write setClickable(false) or setEnabled(false) in this method for all three of your buttons, enable them again when you are starting your animation....hope you got me..

How to stop a Splash Screen with a click before the end?

I created an activity splashScreen in my application.
This works very well with animation is my code :
public class SpalshScreenActivity extends Activity {
private static final int STOPSPLASH = 0;
private static final long SPLASHTIME = 3000;
private boolean flagBack = false;
private final transient Handler splashHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == STOPSPLASH && !flagBack) {
StartMainActivity();
}
super.handleMessage(msg);
}
};
public void onAttachedToWindow() {
super.onAttachedToWindow();
Window window = getWindow();
window.setFormat(PixelFormat.RGBA_8888);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.HideActionBar);
setContentView(R.layout.splash);
StartAnimations();
final Message msg = new Message();
msg.what = STOPSPLASH;
splashHandler.sendMessageDelayed(msg, SPLASHTIME);
}
private void StartAnimations() {
Animation anim = AnimationUtils.loadAnimation(this, R.anim.alpha);
anim.reset();
LinearLayout l=(LinearLayout) findViewById(R.id.lin_lay);
l.clearAnimation();
l.startAnimation(anim);
anim = AnimationUtils.loadAnimation(this, R.anim.translate);
anim.reset();
ImageView iv = (ImageView) findViewById(R.id.logo);
iv.clearAnimation();
iv.startAnimation(anim);
}
private void StartMainActivity() {
final Intent intent = new Intent(SpalshScreenActivity.this, MainFragmentActivity.class);
startActivity(intent);
finish();
}
public boolean onKeyDown(int keyCode, KeyEvent evt) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
flagBack = true;
finish();
return true;
}
return false;
}}
Now I would like to add the ability to click on the screen to stop the SplashScreen.
I tried this way, it works but I think it is not an optimal solution (slow) :
#Override
public boolean onTouchEvent(MotionEvent evt) {
if(evt.getAction() == MotionEvent.ACTION_DOWN) {
flagBack = true;
StartMainActivity();
}
return true;
}
Thank you in advance!
set an OnClickListener to the activity with the same code as in the onTouchEvent

Categories

Resources