How to recognize view movement on screen in Android? - android

I'm working on an SDK for making tutorials. In this SDK I present a spotlight fragment in which I basically create a background canvas there I draw a darker background and a transparent rectangle that focuses on the desired view.
In some cases, this view might move. For example, the developer that uses my SDK creates a timed collapse of a view before the focused view which makes the focused view to move and as a result, my spotlight stays in the wrong location.
The question is: How can I recognize a view movement on the screen so I can update my spotlight fragment accordingly?

The only solution I came up by now is the following 'active' solution, I'm running a Task every half a second that checks the LocationOnScreen of the target view. and if the target view changes it's coordinates I update the fragment. This solution works but I'm still looking for a 'passive' solution that updates me on the location changes instead of testing it every half a second:
#Override
public void onStart() {
super.onStart();
final View targetView = mDrawDataPojo.getWalkthroughMetaPojo().getTargetView().getView();
if (targetView != null) {
targetView.getLocationOnScreen(mOriginalLocationOnScreen);
mTimer = new Timer();
mTimer.schedule(new TargetViewChangeListener(), 0, 500);
}
...
}
#Override
public void onPause() {
super.onPause();
if (mTimer != null) {
mTimer.cancel();
}
...
}
class TargetViewChangeListener extends TimerTask {
public void run() {
int[] currentLocation = new int[2];
mDrawDataPojo.getWalkthroughMetaPojo().getTargetView().getView().getLocationOnScreen(currentLocation);
if (currentLocation[0] != mOriginalLocationOnScreen[0] || currentLocation[1] != mOriginalLocationOnScreen[1]) {
final boolean isActionBar = ABUtils.isActionBarActivity(getActivity());
final int containerId;
try {
mDrawDataPojo.getWalkthroughMetaPojo().setTargetView(new SpotlightTargetView(getActivity(), mDrawDataPojo.getWalkthroughMetaPojo().getTargetView().getView()));
containerId = AndroidUtils.getContainerId(getActivity(), isActionBar);
ABPromotionFragment abPromotionFragment = ABPromotionFragment.newInstance(mDrawDataPojo.getViewDataPojo(), null, mDrawDataPojo.getWalkthroughMetaPojo());
FragmentManager fragmentManager = getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
fragmentTransaction.replace(containerId, abPromotionFragment);
fragmentTransaction.commitAllowingStateLoss();
} catch (Exception e) {
ABLogger.d("TargetViewChangeListener - TimerTask - exception: " + e);
}
}
}
}

Found a much better solution using the OnPreDrawListener:
private final ViewTreeObserver.OnPreDrawListener mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
if (!mAttached) {
removePreDrawObserver(null);
return true;
}
handleViewDraw();
return true;
}
};
The onPreDraw method will be called each time the view is going to be redrawn.
Where handleViewDraw method will look like the follows:
private void handleViewDraw() {
if (if mViewAnchor != null) {
View view = mViewAnchor.get();
if (null != view && view.getVisibility() == VISIBLE) {
view.getLocationOnScreen(mTempLocation);
if (mOldLocation == null) {
mOldLocation = new int[]{mTempLocation[0], mTempLocation[1]};
}
if (isTargetViewLocationChanged()) {
handleVisibleTargetViewLocationChange();
}
mOldLocation[0] = mTempLocation[0];
mOldLocation[1] = mTempLocation[1];
} else {
mView.setVisibility(INVISIBLE);
}
} else {
mView.setVisibility(INVISIBLE);
}
}
private boolean isTargetViewLocationChanged() {
Log.d(TAG, "Old: " + mOldLocation[1] + " ,TEMP: " + mTempLocation[1]);
return mOldLocation[0] != mTempLocation[0] || mOldLocation[1] != mTempLocation[1];
}
Using this method you will be notified only when the view moved, in difference with the 'active' solution that is supplied in the other answer this is a 'passive' solution which will run the handleVisibleTargetViewLocationChange method only when the view has actually moved.

Related

Video is not getting paused in ViewPager

I m using viewpager and its adapter i m displaying image and video as per condition.
I don't have fragment because i m using PagerAdapter.
Code:
pager.setOnPageChangeListener(pageChangeListener);
pager.post(new Runnable() {
#Override
public void run() {
pageChangeListener.onPageSelected(pager.getCurrentItem());
}
});
}
ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
View view = mediaFullScreenImageAdapter.getActiveView(pager);
if (selectedPhotosByDate.get(position).getMessagetype().equalsIgnoreCase("VIDEO")) {
CustomVideoPlayer video_player = (CustomVideoPlayer) view.findViewById(R.id.video_player);
if (video_player.isPlaying()) {
Log.v("THISCALLEDD", "Y" + " : " + position);
video_player.pause();
}
}
}
};
#Nullable
public View getActiveView(final ViewPager viewPager) {
final PagerAdapter adapter = viewPager.getAdapter();
if (null == adapter || adapter.getCount() == 0 || viewPager.getChildCount() == 0) {
return null;
}
int position;
final int currentPosition = viewPager.getCurrentItem();
for (int i = 0; i < viewPager.getChildCount(); i++) {
final View child = viewPager.getChildAt(i);
final ViewPager.LayoutParams layoutParams = (ViewPager.LayoutParams) child.getLayoutParams();
if (layoutParams.isDecor) {
continue;
}
final Field positionField;
try {
positionField = ViewPager.LayoutParams.class.getDeclaredField("position");
positionField.setAccessible(true);
position = positionField.getInt(layoutParams);
} catch (NoSuchFieldException e) {
break;
} catch (IllegalAccessException e) {
break;
}
if (position == currentPosition) {
return child;
}
}
return null;
}
Update:
selectedPhotosByDate = appDatabase.chatMessagesDao().getMediaByGroupId(topicid, "Y");
if (selectedPhotosByDate.size() > 0 && selectedPhotosByDate != null) {
mediaFullScreenImageAdapter = new MediaFullScreenImageAdapter(MediaFullScreenSlideActivity.this, selectedPhotosByDate);
pager.setAdapter(mediaFullScreenImageAdapter);
for (int i = 0; i < selectedPhotosByDate.size(); i++) {
if (messageid == selectedPhotosByDate.get(i).getMessageId()) {
position = i;
break;
}
}
pager.setCurrentItem(position);
pager.setOffscreenPageLimit(selectedPhotosByDate.size());
}
I am able to get logcat value . But my video doesn't get pause.
If my video is playing and user swipe for other item playing video must be paused.
Advanced help would be appreciated!
Based on the documentation here, onPageSelected is called when a new page is selected. That means, the active view that you are trying to get using the currentItem from the ViewPager will return you the current selected item rather than the previously selected item. So your reference to video_player is also wrong and hence it is not working.
A simple way to do this is to have a variable currentPosition. Update it in onPageSelected but before updating, get its view and pause the video. This way whenever you access it, you will first get the previous index and then you will update it to the current index for the next time.
As per my understanding ,you want to pause previous video when user swipe in viewpager .
#Override
public void onPageSelected(int position) {
View view = mediaFullScreenImageAdapter.getActiveView(pager);
if (selectedPhotosByDate.get(position).getMessagetype().equalsIgnoreCase("VIDEO")) {
CustomVideoPlayer video_player = (CustomVideoPlayer) view.findViewById(R.id.video_player);
if (video_player.isPlaying()) {
Log.v("THISCALLEDD", "Y" + " : " + position);
video_player.pause();
}
}
}
you are getting view object of current active position ,but you want to pause video of (position - 1 ),you need to have view object of previous position .
Finally resolved the issue.
I moved this code
View view = mediaFullScreenImageAdapter.getActiveView(pager);
CustomVideoPlayer video_player = (CustomVideoPlayer) view.findViewById(R.id.video_player);
video_player.pause();
to onPageScrolled() method instead of onPageSelected() method.
This worked for me with a Youtube video playing as an embedded iFrame in a WebView:
viewPager.addOnPageChangeListener(object : SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) {
// NOTE: this workaround pauses any playing Youtube video in the WebView, if the video screen is being switched out.
// This works by getting the ViewPager#focusedChild, which will be the WebView if that screen is currently in focus,
// before the next selected ViewPager screen gets switched-to/loaded.
viewPager.focusedChild?.findViewById<WebView>(R.id.video_view)?.onPause()
// NOTE: we do a postDelay below, to ensure the WebView gets put back into its resume state, if it being switched to.
// This is delayed, so that this happens after the ViewPager screen with the WebView, has time to load it into place.
postDelayed({ viewPager.focusedChild?.findViewById<WebView>(R.id.video_view)?.onResume() }, 200)
}
})

How to simply save image to photo gallery

I'm playing with a drawing activity in Java converted/decompiled from this Kotlin sample.
I'm simplifying its functionalities and, as it is now, it allows me to click on "Save" button and a preview pops up with a text saying "Saved!", but I'd like to know what needs to be done to simply throw the resulting image to the Android photo gallery anytime the button is clicked (let's say, after saved, the image must become a standalone picture inside the camera gallery).
It seems it has to do with FileOutputStream/Bitmap.CompressFormat/MediaStore.Images
and I can foresee some difficulties in terms of naming files in a way they don't overwrite and I'm reading a lot of answers around here, but I still didn't get the logic so any idea is appreciated.
It's the first time I'm trying to do something similar so I'm sort of lost and I come here to ask for some directions.
Here is the single activity:
public final class SampleActivity extends AppCompatActivity implements OnSeekBarChangeListener, OnClickListener {
private HashMap _$_findViewCache;
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_sample);
(this._$_findCachedViewById(id.close)).setOnClickListener(this);
(this._$_findCachedViewById(id.save)).setOnClickListener(this);
(this._$_findCachedViewById(id.undo)).setOnClickListener(this);
(this._$_findCachedViewById(id.clear)).setOnClickListener(this);
((SeekBar)this._$_findCachedViewById(id.red)).setOnSeekBarChangeListener(this);
((SeekBar)this._$_findCachedViewById(id.green)).setOnSeekBarChangeListener(this);
((SeekBar)this._$_findCachedViewById(id.blue)).setOnSeekBarChangeListener(this);
((SeekBar)this._$_findCachedViewById(id.width)).setOnSeekBarChangeListener(this);
}
public void onProgressChanged(#Nullable SeekBar seekBar, int progress, boolean fromUser) {
int var10000;
SeekBar var10001;
label58: {
label50: {
if (seekBar != null) {
var10000 = seekBar.getId();
var10001 = (SeekBar)this._$_findCachedViewById(id.red);
Intrinsics.checkExpressionValueIsNotNull(var10001, "red");
if (var10000 == var10001.getId()) {
break label50;
}
}
if (seekBar != null) {
var10000 = seekBar.getId();
var10001 = (SeekBar)this._$_findCachedViewById(id.green);
Intrinsics.checkExpressionValueIsNotNull(var10001, "green");
if (var10000 == var10001.getId()) {
break label50;
}
}
if (seekBar == null) {
break label58;
}
var10000 = seekBar.getId();
var10001 = (SeekBar)this._$_findCachedViewById(id.blue);
Intrinsics.checkExpressionValueIsNotNull(var10001, "blue");
if (var10000 != var10001.getId()) {
break label58;
}
}
SeekBar var8 = (SeekBar)this._$_findCachedViewById(id.red);
Intrinsics.checkExpressionValueIsNotNull(var8, "red");
int r = var8.getProgress();
var8 = (SeekBar)this._$_findCachedViewById(id.green);
Intrinsics.checkExpressionValueIsNotNull(var8, "green");
int g = var8.getProgress();
var8 = (SeekBar)this._$_findCachedViewById(id.blue);
Intrinsics.checkExpressionValueIsNotNull(var8, "blue");
int b = var8.getProgress();
int color = Color.argb(255, r, g, b);
((FingerPaintImageView)this._$_findCachedViewById(id.finger)).setStrokeColor(color);
(this._$_findCachedViewById(id.colorPreview)).setBackgroundColor(color);
return;
}
if (seekBar != null) {
var10000 = seekBar.getId();
var10001 = (SeekBar)this._$_findCachedViewById(id.width);
Intrinsics.checkExpressionValueIsNotNull(var10001, "width");
if (var10000 == var10001.getId()) {
((FingerPaintImageView)this._$_findCachedViewById(id.finger)).setStrokeWidth((float)progress);
}
}
}
public void onClick(#Nullable View v) {
if (Intrinsics.areEqual(v, this._$_findCachedViewById(id.undo))) {
((FingerPaintImageView)this._$_findCachedViewById(id.finger)).undo();
} else if (Intrinsics.areEqual(v, this._$_findCachedViewById(id.clear))) {
((FingerPaintImageView)this._$_findCachedViewById(id.finger)).clear();
} else if (Intrinsics.areEqual(v, this._$_findCachedViewById(id.close))) {
this.hidePreview();
} else if (Intrinsics.areEqual(v, this._$_findCachedViewById(id.save))) {
this.showPreview();
}
}
private final void showPreview() {
RelativeLayout var10000 = (RelativeLayout)this._$_findCachedViewById(id.previewContainer);
Intrinsics.checkExpressionValueIsNotNull(var10000, "previewContainer");
var10000.setVisibility(View.VISIBLE);
ImageView var1 = (ImageView)this._$_findCachedViewById(id.preview);
FingerPaintImageView var10001 = (FingerPaintImageView)this._$_findCachedViewById(id.finger);
Intrinsics.checkExpressionValueIsNotNull(var10001, "finger");
var1.setImageDrawable(var10001.getDrawable());
}
private final void hidePreview() {
RelativeLayout var10000 = (RelativeLayout)this._$_findCachedViewById(id.previewContainer);
Intrinsics.checkExpressionValueIsNotNull(var10000, "previewContainer");
var10000.setVisibility(View.GONE);
}
public void onStartTrackingTouch(#Nullable SeekBar seekBar) {
}
public void onStopTrackingTouch(#Nullable SeekBar seekBar) {
}
public void onBackPressed() {
RelativeLayout var10000 = (RelativeLayout)this._$_findCachedViewById(id.previewContainer);
Intrinsics.checkExpressionValueIsNotNull(var10000, "previewContainer");
if (var10000.getVisibility() == View.VISIBLE) {
this.hidePreview();
} else {
super.onBackPressed();
}
}
public View _$_findCachedViewById(int var1) {
if (this._$_findViewCache == null) {
this._$_findViewCache = new HashMap();
}
View var2 = (View)this._$_findViewCache.get(var1);
if (var2 == null) {
var2 = this.findViewById(var1);
this._$_findViewCache.put(var1, var2);
}
return var2;
}
public void _$_clearFindViewByIdCache() {
if (this._$_findViewCache != null) {
this._$_findViewCache.clear();
}
}
}
Thanks in advance!
I was able to overcome this issue by taking another paint-like sample (a simpler one and in Java) called Android Drawable View.
This different sample and tips from previous answers available here on StackOverflow like this one and this other one were enough to put the project together so I'll try to explain how to.
First, you need to add permission to WRITE_EXTERNAL_STORAGE in your Manifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Later, you just need to add a save button to your activity_main.xml:
<Button
android:id="#+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save" />
Then, you initialize the button view onCreate and associate the new saveButton with a setOnClickListener and don't forget to request permission in realtime:
Button saveButton = findViewById(R.id.saveButton);
saveButton.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
if (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED) {
drawableView.setEnabled(true);
}
else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]
{ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
}
Bitmap bm = drawableView.obtainBitmap();
MediaStore.Images.Media.insertImage(getContentResolver(), bm, "title" , "description");
}
});
By using the method described above, I've been able to save a new media file inside a folder in the default gallery app on the emulator as you can see below:
However, it's still getting an unintended black background that I must overcome now, but I consider the initial issue solved as it answers my own original question.

ListView refreshing by runOnUiThread(run) not working

So im quite new to Android Studio and app development in general and i had this issue for a while, with no luck of fixing it. I've figured that someone here might provide some ideas for fixing this..
Issue: The refreshing of ListView on UI thread (as suggested here) does not work for me. Here's the declaration of 'Runnable run' (in MainActivity.java):
public Runnable run;
// ...
run = new Runnable() {
public void run() {
ArrayList<String> temp1 = (ArrayList<String>) arrayList_1.clone();
View v = getLayoutInflater().inflate(R.layout.fragment_main, null);
lv_1 = (ListView) v.findViewById(R.id.listViewMe);
lv_1.setAdapter(adapter_1);
arrayList_1.clear();
arrayList_1.addAll(temp1);
adapter_1.notifyDataSetChanged();
lv_1.invalidateViews();
lv_1.refreshDrawableState();
Log.e("gig", "DONE REFRESHING");
}
};
I call the method here:
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
int id = item.getItemId();
Fragment fragment = null;
if (id == R.id.nav_main) {
fragment = new FragmentMain();
} if (id == R.id.nav_history) {
fragment = new FragmentHistory();
}
if (fragment != null)
{
FragmentTransaction localFragmentTransaction = getSupportFragmentManager().beginTransaction();
localFragmentTransaction.replace(R.id.screen_area, fragment);
localFragmentTransaction.commit();
runOnUiThread(run); // here
}
((DrawerLayout) findViewById(R.id.drawer_layout)).closeDrawer(GravityCompat.START);
return true;
}
Now for the part that's confusing me: it works when i add a new item to the ListView via this method:
public void addDebtToOther(String name, String money)
{
String full = name + ", " + money + " EUR";
lv_1 = (ListView) findViewById(R.id.listViewMe);
if (lv_1!=null) {
lv_1.setAdapter(adapter_1);
arrayList_1.add(full);
adapter_1.notifyDataSetChanged();
} else {
Log.e("gig", "ListView error, lv is NULL");
}
}
That's about it, any help would be really apriciated!
In the run object, a new View is inflated, but as far as I can tell, it's not being added to the Activity's contentView or any of it's children, so it is just a View somewhere in memory that isn't being rendered onto the screen.
Did you mean to do something like this instead?:
public Runnable run;
// ...
run = new Runnable() {
public void run() {
ArrayList<String> temp1 = (ArrayList<String>) arrayList_1.clone();
// View v = getLayoutInflater().inflate(R.layout.fragment_main, null);
// lv_1 = (ListView) v.findViewById(R.id.listViewMe);
lv_1 = (ListView) findViewById(R.id.listViewMe);
lv_1.setAdapter(adapter_1);
arrayList_1.clear();
arrayList_1.addAll(temp1);
adapter_1.notifyDataSetChanged();
lv_1.invalidateViews();
lv_1.refreshDrawableState();
Log.e("gig", "DONE REFRESHING");
}
};
Ok so after about a week of head-banging, with the help of #Eric i've figured it out. Turns out i needed to call the run() method in my fragment's .onStart(), like this:
#Override
public void onStart() {
super.onStart();
((MainActivity)getContext()).run.run();
}
Thanks again Eric!

Keep GridView when resuming from sleep mode

I got a problem with a quite large GridView.(about 70 children) The GridView works fine if I start it on onCreate or after resumeing after pressing the home button and then return. But when I resume after coming back from sleep mode, my BaseAdapter starts again and ruin the changes I have done to it during runtime. This also make getChildAt() give a NullPointerException if I am calling it just after restart.
How can I make it just do what regular onPause(home button) does to the GridView, and avoid that the GridView is wiped out everytime I am resumeing from sleep mode?
Edit:
I have tried setting a wakelock for my Activity class that calls the BaseAdpter with no luck
2.Edit: Since I posted this question I have played around with trying to restore the GridView using this code in onPause:
SparseArray<Parcelable> array = new SparseArray<Parcelable>();
gridView.saveHierarchyState(array);
bundle = new Bundle();
bundle.putSparseParcelableArray("state", array);
And this in onResume:
try{
gridView.restoreHierarchyState(bundle.getSparseParcelableArray("state"));
}
catch(Exception e){
//Most likely first start
Log.i("SomeTag", "No GridView state found");
}
}
The strange thing is everything I seems to have jumped from one place to another on the screen and it is still crashing when I try to getChildAt(). It is also failing to get it after sleep mode.
Edit Here is the code from BaseAdapter getView(Note! some of this code is irrelevant)
public View getView (int position, View convertView, ViewGroup parent) {
mParentView = parent;
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
//sets the height for every individual box
int box = width/7*6/10;
ImageCell v = null;
if (convertView == null) {
// If it's not recycled, create a new ImageCell.
v = new ImageCell (mContext);
v.setLayoutParams(new GridView.LayoutParams(box, box));
v.setScaleType(ImageView.ScaleType.CENTER_CROP);
v.setPadding(0, 0, 0, 0);
} else {
v = (ImageCell) convertView;
}
v.mCellNumber = position;
v.mGrid = (GridView) mParentView;
v.mEmpty = true;
int id = 200;
v.setId(++id);
String map = str[position];
int pos = position;
int up = pos-10;
int down = pos+10;
int left = pos-1;
int right = pos+1;
if(up>=0){
above = str[up];
}
else{
//Do nothing
}
if(down<70){
under = str[down];
}
else{
//Do nothing
}
if(left<=-1){
//Do nothing
}
else{
lefte=str[left];
}
if(right>=70){
//Do nothing
}
else{
righte=str[right];
}
//if(left>-1|left!=9|left!=19|left!=29|left!=39|left!=49|left!=59){
// lefte = str[left];
// }
// else{
// Log.i("ImageCellAdapter", "Left is trying to break walls "+left);
//Do nothing
// }
if (map.equals("mountain")) {
//Checks surroundings to find out witch drawable to set
v.setBackgroundResource(R.color.cell_empty);
v.mEmpty = false;
//All
if(above=="mountain"&&under=="mountain"&&lefte=="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_full);
}
//Single
else if(above=="mountain"&&under!="mountain"&&lefte!="mountain"&&righte!="mountain"){
v.setImageResource(R.drawable.mountain_down);
}
else if(above!="mountain"&&under=="mountain"&&lefte!="mountain"&&righte!="mountain"){
v.setImageResource(R.drawable.mountain_up);
}
else if(above!="mountain"&&under!="mountain"&&lefte!="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_left);
}
else if(above!="mountain"&&under!="mountain"&&lefte=="mountain"&&righte!="mountain"){
v.setImageResource(R.drawable.mountain_right);
}
//Double
else if(above=="mountain"&&under!="mountain"&&lefte!="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_left_down);
}
else if(above!="mountain"&&under=="mountain"&&lefte!="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_left_up);
}
else if(above=="mountain"&&under!="mountain"&&lefte=="mountain"&&righte!="mountain"){
v.setImageResource(R.drawable.mountain_right_down);
}
else if(above!="mountain"&&under=="mountain"&&lefte=="mountain"&&righte!="mountain"){
v.setImageResource(R.drawable.mountain_up_right);
}
else if(above!="mountain"&&under!="mountain"&&lefte=="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_up_down);
}
else if(above=="mountain"&&under=="mountain"&&lefte!="mountain"&&righte!="mountain"){
v.setImageResource(R.drawable.mountain_up_down);
}
//Triple
else if(above!="mountain"&&under=="mountain"&&lefte=="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_left_right_down);
}
else if(above=="mountain"&&under=="mountain"&&lefte=="mountain"&&righte!="mountain"){
v.setImageResource(R.drawable.mountain_left_up_down);
}
else if(above=="mountain"&&under!="mountain"&&lefte=="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_left_up_right);
}
else if(above=="mountain"&&under=="mountain"&&lefte!="mountain"&&righte=="mountain"){
v.setImageResource(R.drawable.mountain_up_right_down);
}
//None
else{
v.setImageResource(R.drawable.mountain);
}
}
else if(map=="start"){
List<String> posOf = Arrays.asList(str);
startPos=posOf.indexOf("start");
v.mEmpty=false;
v.setBackgroundResource(R.color.cell_empty);
getDur();
BitmapDrawable first = (BitmapDrawable)mContext.getResources().getDrawable(R.drawable.gress);
BitmapDrawable second =(BitmapDrawable)mContext.getResources().getDrawable(R.drawable.ic_launcher);
BitmapDrawable third = (BitmapDrawable)mContext.getResources().getDrawable(R.drawable.gress);
BitmapDrawable fourth = (BitmapDrawable)mContext.getResources().getDrawable(R.drawable.ic_launcher);
final AnimationDrawable ani = new AnimationDrawable();
ani.addFrame(first, duration);
ani.addFrame(second, duration);
ani.addFrame(third, duration);
ani.addFrame(fourth, duration);
ani.setOneShot(true);
v.setImageDrawable(ani);
checkIfAnimationDone(ani);
v.post(new Runnable() {
public void run() {
ani.start();
}
});
}
else if(map=="stop"){
v.mEmpty=false;
v.setBackgroundResource(R.color.cell_empty);
v.setImageResource(R.drawable.ic_launcher);
v.setTag(1);
}
else if(map=="grass"){
v.mEmpty=false;
v.setBackgroundResource(R.drawable.gress);
}
else{
// v.setBackgroundResource (R.color.drop_target_enabled);
v.setBackgroundResource (R.color.cell_empty);
}
//v.mGrid.requestDisallowInterceptTouchEvent (true);
//v.setImageResource (R.drawable.hello);
// Set up to relay events to the activity.
// The activity decides which events trigger drag operations.
// Activities like the Android Launcher require a long click to get a drag operation started.
return v;
}
And defining the GridView in onCreate:
gridView= new BoxView(this);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){
w.getDefaultDisplay().getSize(size);
Measuredwidth = size.x;
Measuredheight = size.y;
}else{
Display d = w.getDefaultDisplay();
Measuredwidth = d.getWidth();
Measuredheight = d.getHeight();
}
int width = Measuredwidth/7*6;
gridView.setLayoutParams(new GridView.LayoutParams(width,LayoutParams.FILL_PARENT, Gravity.CENTER_HORIZONTAL));
gridView.setNumColumns(columns);
gridView.setVerticalSpacing(0);
gridView.setHorizontalSpacing(0);
gridView.setPadding(0, 0, 0, 0);
gridView.setId(101);
gridView.setSelector(android.R.color.transparent);
gridView.setAdapter (new ImageCellAdapter(this, MAP));
I have noticed one thing in you code:
gridView.setLayoutParams(new GridView.LayoutParams(width,LayoutParams.FILL_PARENT, Gravity.CENTER_HORIZONTAL));
Even if GridView is a ViewGroup, you can't access it's LayoutParams. Just think it trough, if this would be possible that means you could put a GridView inside another GridView.
Fix this before going further because is messing with you.
If you want your GridView to be inside a LinearLayout, for example, try this:
gridView.setLayoutParams(new LinearLayout.LayoutParams(width,LayoutParams.FILL_PARENT, Gravity.CENTER_HORIZONTAL));
Here is the correct implementation of this answer:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*You have to implement what things from the gridView sould be "saved"*/
GridView gridView = new GridView(this) {
#Override
public Parcelable onSaveInstanceState() {
// Create the Parceable object with the things you want to save
Parceable stateOfGrid = ....etc
return stateOfGrid;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
// Restore your grid's parameters that you previously implemented in onSaveInstanceState
super.onRestoreInstanceState(state);
...
}
};
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
Parcelable state = savedInstanceState.getParcelable("state");
if (state != null) {
gridView.onRestoreInstanceState(state);
Log.d(this.getClass().getName(), "state restored!");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// Put your grid's Parceable into the bundle
super.onSaveInstanceState(outState);
Parcelable state = gridView.onSaveInstanceState();
outState.putParcelable("state", state);
}
}
Try using this tag:
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
You can use onSaveInstanceState (Bundle outState)
to save state of your gridview
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable state = gridView.onSaveInstanceState();
outState.putParcelable("state", state);
}
then in onCreate after you seted adapter to grdiview add this code
if (savedInstanceState != null) {
Parcelable state = savedInstanceState.getParcelable("state");
if (state != null) {
gridView.onRestoreInstanceState(state);
Log.d(this.getClass().getName(), "state restored!");
}
}
Is your application running in Landscape Mode?
if yes, then you should consider adding the tag
"android:configChanges="keyboard|keyboardHidden|orientation" for your activity in Manifest.xml, which will prevent android system from killing your activity and restarting it when you unlock the screen.

FragmentDialog can't be found by tag right after adding it to the getSupportFragmentManager

Any of you ever experience a fragment not been found after adding it to the fragment manager? When we try to hide it, it stays stuck on screen.
From fragment:onActivityCreated we show the dialog:
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
// Push the progress dialog
String text = getActivity().getString(R.string.httpLoadingData);
((BaseFragmentActivity) getActivity()).showHttpWaitingDialog(text);
...
}
Later from the same fragment inside a new thread We hide the dialog:
private void prepareInitialWebViewData() {
initialFragmentWebDataLoadingThread = new Thread(new Runnable() {
#Override
public void run() {
updateDataAndView();
BaseFragmentActivity activity = (BaseFragmentActivity) getActivity();
BaseFragmentActivity activity = (BaseFragmentActivity) getActivity();
if (activity != null)
{
activity.hideHttpWaitingDialog();
}
// We don't need to keep this handle any longer since we've done
// the work
initialFragmentWebDataLoadingThread = null;
}
});
initialFragmentWebDataLoadingThread.start();
}
Here is the code found in our BaseFragmentActivity for both show and hide. Note that it is possible to call the showdialog many times, so we keep a refcount.
First the show function:
public void showHttpWaitingDialog(CharSequence title)
{
synchronized (mRefCount)
{
mRefCount++;
Log.w("showhideHttpWaitingDialog", "++mRefCount:" + mRefCount + ", Title:" + title);
FragmentManager fm = getSupportFragmentManager();
if (fm != null)
{
Fragment frag = fm.findFragmentByTag("httpWaitDialog");
if (frag == null)
{
WaitingOnHttpFragmentDialog dialog = WaitingOnHttpFragmentDialog.newInstance(title);
fm.beginTransaction().add(dialog, "httpWaitDialog").commit();
}
}
else
Log.w("showhideHttpWaitingDialog", "fragman == null");
}
}
Then the hide function:
public void hideHttpWaitingDialog()
{
synchronized (mRefCount)
{
Log.w("showhideHttpWaitingDialog", "--mRefCount:" + mRefCount);
if (mRefCount < 0)
{
Log.w("showhideHttpWaitingDialog", "Why are you trying to hide something that doesn't exists?");
mRefCount = 0;
}
else
{
if (mRefCount == 0)
{
FragmentManager fragman = getSupportFragmentManager();
if (fragman != null)
{
Fragment frag = fragman.findFragmentByTag("httpWaitDialog");
if (frag != null)
{
fragman.beginTransaction().remove(frag).commit();
Log.w("showhideHttpWaitingDialog", "dismissed normally");
}
else
Log.w("showhideHttpWaitingDialog", "httpWaitDialog not found!");
}
}
}
}
}
I can tell you what your problem is... you can't update the UI in any other thread than the UI thread.
I don't know how to fix it myself, but a quick search reveals the following questions which may be useful.
SO Question 1
SO Question 2
The second one seems like it would apply more closely to your current code.

Categories

Resources