Clean up controller logic

tempwork
Floens 10 years ago
parent 62d1f4052d
commit a2561ff860
  1. 20
      Clover/app/src/main/java/org/floens/chan/controller/Controller.java
  2. 67
      Clover/app/src/main/java/org/floens/chan/controller/ControllerLogic.java
  3. 6
      Clover/app/src/main/java/org/floens/chan/controller/ControllerTransition.java
  4. 129
      Clover/app/src/main/java/org/floens/chan/controller/NavigationController.java
  5. 42
      Clover/app/src/main/java/org/floens/chan/controller/PushControllerTransition.java
  6. 17
      Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java
  7. 17
      Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
  8. 8
      Clover/app/src/main/java/org/floens/chan/ui/activity/BoardActivity.java
  9. 6
      Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
  10. 7
      Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
  11. 37
      Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java
  12. 8
      Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java
  13. 2
      Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java
  14. 8
      Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
  15. 3
      Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsController.java
  16. 10
      Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java
  17. 15
      Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java

@ -28,28 +28,28 @@ public abstract class Controller {
public Context context;
public View view;
public Controller stackSiblingController;
public NavigationController navigationController;
public NavigationItem navigationItem = new NavigationItem();
public Controller previousSibling;
public NavigationController navigationController;
public Controller(Context context) {
this.context = context;
}
public void onCreate() {
// Logger.test(getClass().getSimpleName() + " onCreate");
}
public void onShow() {
// Logger.test(getClass().getSimpleName() + " onShow");
}
public void onHide() {
// Logger.test(getClass().getSimpleName() + " onHide");
}
public void onDestroy() {
}
public View inflateRes(int resId) {
return LayoutInflater.from(context).inflate(resId, null);
// Logger.test(getClass().getSimpleName() + " onDestroy");
}
public void onConfigurationChanged(Configuration newConfig) {
@ -59,6 +59,14 @@ public abstract class Controller {
return false;
}
public void presentController(Controller controller) {
}
public View inflateRes(int resId) {
return LayoutInflater.from(context).inflate(resId, null);
}
public String string(int id) {
return context.getString(id);
}

@ -0,0 +1,67 @@
package org.floens.chan.controller;
import android.view.ViewGroup;
import org.floens.chan.utils.AndroidUtils;
public class ControllerLogic {
public static void attach(Controller controller, ViewGroup view, boolean over) {
if (over) {
view.addView(controller.view,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
);
} else {
view.addView(controller.view, 0,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
);
}
}
public static void detach(Controller controller) {
AndroidUtils.removeFromParentView(controller.view);
}
public static void transition(Controller from, Controller to, boolean destroyFrom, boolean createTo, ViewGroup toView, boolean viewOver) {
if (createTo) {
to.onCreate();
}
attach(to, toView, viewOver);
to.onShow();
if (from != null) {
from.onHide();
detach(from);
if (destroyFrom) {
from.onDestroy();
}
}
}
public static void startTransition(Controller from, Controller to, boolean destroyFrom, boolean createTo, ViewGroup toView, boolean viewOver, ControllerTransition transition) {
transition.destroyFrom = destroyFrom;
transition.from = from;
transition.to = to;
if (createTo) {
to.onCreate();
}
attach(to, toView, viewOver);
to.onShow();
transition.perform();
}
public static void finishTransition(ControllerTransition transition) {
if (transition.from != null) {
transition.from.onHide();
detach(transition.from);
if (transition.destroyFrom) {
transition.from.onDestroy();
}
}
}
}

@ -22,11 +22,13 @@ public abstract class ControllerTransition {
public Controller from;
public Controller to;
public boolean destroyFrom;
public boolean viewOver;
public abstract void perform();
public void onCompleted() {
this.callback.onControllerTransitionCompleted();
this.callback.onControllerTransitionCompleted(this);
}
public void setCallback(Callback callback) {
@ -34,6 +36,6 @@ public abstract class ControllerTransition {
}
public interface Callback {
public void onControllerTransitionCompleted();
public void onControllerTransitionCompleted(ControllerTransition transition);
}
}

@ -20,11 +20,9 @@ package org.floens.chan.controller;
import android.content.Context;
import android.content.res.Configuration;
import android.support.v4.widget.DrawerLayout;
import android.view.View;
import android.widget.FrameLayout;
import org.floens.chan.ui.toolbar.Toolbar;
import org.floens.chan.utils.AndroidUtils;
import java.util.ArrayList;
import java.util.List;
@ -37,47 +35,60 @@ public abstract class NavigationController extends Controller implements Control
private List<Controller> controllerList = new ArrayList<>();
private ControllerTransition controllerTransition;
private boolean blockingInput = true;
private boolean blockingInput = false;
public NavigationController(Context context, final Controller startController) {
public NavigationController(Context context) {
super(context);
}
public boolean pushController(final Controller to) {
return pushController(to, true);
}
public boolean pushController(final Controller to, boolean animated) {
return pushController(to, animated ? new PushControllerTransition() : null);
}
public boolean pushController(final Controller to, ControllerTransition controllerTransition) {
if (blockingInput) return false;
if (controllerTransition != null) {
if (this.controllerTransition != null) {
throw new IllegalArgumentException("Cannot push controller while a transition is in progress.");
}
blockingInput = true;
final Controller from = controllerList.get(controllerList.size() - 1);
to.stackSiblingController = from;
final Controller from = controllerList.size() > 0 ? controllerList.get(controllerList.size() - 1) : null;
to.navigationController = this;
to.onCreate();
to.previousSibling = from;
controllerList.add(to);
this.controllerTransition = new PushControllerTransition();
container.addView(to.view, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
AndroidUtils.waitForMeasure(to.view, new AndroidUtils.OnMeasuredCallback() {
@Override
public void onMeasured(View view) {
to.onShow();
if (controllerTransition != null) {
blockingInput = true;
this.controllerTransition = controllerTransition;
controllerTransition.setCallback(this);
doTransition(true, from, to, controllerTransition);
}
});
ControllerLogic.startTransition(from, to, false, true, container, true, controllerTransition);
toolbar.setNavigationItem(true, true, to.navigationItem);
} else {
ControllerLogic.transition(from, to, false, true, container, true);
toolbar.setNavigationItem(false, true, to.navigationItem);
}
return true;
}
public boolean popController() {
return popController(true);
}
public boolean popController(boolean animated) {
return popController(animated ? new PopControllerTransition() : null);
}
public boolean popController(ControllerTransition controllerTransition) {
if (blockingInput) return false;
if (controllerTransition != null) {
if (this.controllerTransition != null) {
throw new IllegalArgumentException("Cannot pop controller while a transition is in progress.");
}
@ -85,46 +96,36 @@ public abstract class NavigationController extends Controller implements Control
throw new IllegalArgumentException("Cannot pop with 1 controller left");
}
blockingInput = true;
final Controller from = controllerList.get(controllerList.size() - 1);
final Controller to = controllerList.get(controllerList.size() - 2);
this.controllerTransition = new PopControllerTransition();
container.addView(to.view, 0, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
AndroidUtils.waitForMeasure(to.view, new AndroidUtils.OnMeasuredCallback() {
@Override
public void onMeasured(View view) {
to.onShow();
if (controllerTransition != null) {
blockingInput = true;
this.controllerTransition = controllerTransition;
controllerTransition.setCallback(this);
doTransition(false, from, to, controllerTransition);
}
});
ControllerLogic.startTransition(from, to, true, false, container, false, controllerTransition);
toolbar.setNavigationItem(true, false, to.navigationItem);
} else {
ControllerLogic.transition(from, to, true, false, container, false);
toolbar.setNavigationItem(false, false, to.navigationItem);
}
return true;
}
public Controller getPreviousSibling(Controller controller) {
int index = controllerList.indexOf(controller);
if (index > 0) {
return controllerList.get(index - 1);
} else {
return null;
}
public void setControllerList(List<Controller> controllers) {
}
@Override
public void onControllerTransitionCompleted() {
if (controllerTransition instanceof PushControllerTransition) {
controllerTransition.from.onHide();
container.removeView(controllerTransition.from.view);
} else if (controllerTransition instanceof PopControllerTransition) {
controllerList.remove(controllerTransition.from);
controllerTransition.from.onHide();
container.removeView(controllerTransition.from.view);
controllerTransition.from.onDestroy();
public void onControllerTransitionCompleted(ControllerTransition transition) {
ControllerLogic.finishTransition(transition);
if (transition.destroyFrom) {
controllerList.remove(transition.from);
}
this.controllerTransition = null;
blockingInput = false;
}
@ -158,40 +159,12 @@ public abstract class NavigationController extends Controller implements Control
toolbar.onConfigurationChanged(newConfig);
}
public void initWithController(final Controller controller) {
controllerList.add(controller);
controller.navigationController = this;
controller.onCreate();
toolbar.setNavigationItem(false, true, controller.navigationItem);
container.addView(controller.view, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
AndroidUtils.waitForMeasure(controller.view, new AndroidUtils.OnMeasuredCallback() {
@Override
public void onMeasured(View view) {
onCreate();
onShow();
controller.onShow();
blockingInput = false;
}
});
}
public void onMenuClicked() {
}
private void doTransition(boolean pushing, Controller from, Controller to, ControllerTransition transition) {
transition.setCallback(this);
transition.from = from;
transition.to = to;
transition.perform();
toolbar.setNavigationItem(true, pushing, to.navigationItem);
}
@Override
public void onMenuBackClicked(boolean isArrow) {
public void onMenuOrBackClicked(boolean isArrow) {
if (isArrow) {
onBack();
} else {

@ -25,30 +25,38 @@ import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import org.floens.chan.utils.AndroidUtils;
public class PushControllerTransition extends ControllerTransition {
@Override
public void perform() {
Animator fromAlpha = ObjectAnimator.ofFloat(from.view, View.ALPHA, 1f, 0.7f);
fromAlpha.setDuration(217);
fromAlpha.setInterpolator(new AccelerateDecelerateInterpolator()); // new PathInterpolator(0.4f, 0f, 0.2f, 1f)
AndroidUtils.waitForMeasure(to.view, new AndroidUtils.OnMeasuredCallback() {
@Override
public boolean onMeasured(View view) {
Animator fromAlpha = ObjectAnimator.ofFloat(from.view, View.ALPHA, 1f, 0.7f);
fromAlpha.setDuration(217);
fromAlpha.setInterpolator(new AccelerateDecelerateInterpolator()); // new PathInterpolator(0.4f, 0f, 0.2f, 1f)
Animator toAlpha = ObjectAnimator.ofFloat(to.view, View.ALPHA, 0f, 1f);
toAlpha.setDuration(200);
toAlpha.setInterpolator(new DecelerateInterpolator(2f));
Animator toAlpha = ObjectAnimator.ofFloat(to.view, View.ALPHA, 0f, 1f);
toAlpha.setDuration(200);
toAlpha.setInterpolator(new DecelerateInterpolator(2f));
Animator toY = ObjectAnimator.ofFloat(to.view, View.Y, to.view.getHeight() * 0.08f, 0f);
toY.setDuration(350);
toY.setInterpolator(new DecelerateInterpolator(2.5f));
Animator toY = ObjectAnimator.ofFloat(to.view, View.Y, to.view.getHeight() * 0.08f, 0f);
toY.setDuration(350);
toY.setInterpolator(new DecelerateInterpolator(2.5f));
toY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
onCompleted();
toY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
onCompleted();
}
});
AnimatorSet set = new AnimatorSet();
set.playTogether(fromAlpha, toAlpha, toY);
set.start();
return false;
}
});
AnimatorSet set = new AnimatorSet();
set.playTogether(fromAlpha, toAlpha, toY);
set.start();
}
}

@ -0,0 +1,17 @@
package org.floens.chan.core.model;
public class PostImage {
public String thumbnailUrl;
public String imageUrl;
public String filename;
public int imageWidth;
public int imageHeight;
public PostImage(String thumbnailUrl, String imageUrl, String filename, int imageWidth, int imageHeight) {
this.thumbnailUrl = thumbnailUrl;
this.imageUrl = imageUrl;
this.filename = filename;
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
}
}

@ -25,14 +25,15 @@ import com.android.volley.VolleyError;
import org.floens.chan.ChanApplication;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.core.loader.ChanLoader;
import org.floens.chan.core.loader.LoaderPool;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post;
import org.floens.chan.core.model.PostImage;
import org.floens.chan.core.model.PostLinkable;
import org.floens.chan.core.model.SavedReply;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.adapter.PostAdapter;
import org.floens.chan.ui.view.PostView;
import org.floens.chan.utils.AndroidUtils;
@ -134,7 +135,19 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
@Override
public void onThumbnailClicked(Post post) {
List<PostImage> images = new ArrayList<>();
int index = -1;
for (int i = 0; i < chanLoader.getThread().posts.size(); i++) {
Post item = chanLoader.getThread().posts.get(i);
if (item.hasImage) {
images.add(new PostImage(item.thumbnailUrl, item.imageUrl, item.filename, item.imageWidth, item.imageHeight));
if (item.no == post.no) {
index = i;
}
}
}
threadPresenterCallback.showImages(images, index);
}
@Override
@ -312,5 +325,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
public void openLink(String link);
public void showPostsPopup(Post forPost, List<Post> posts);
public void showImages(List<PostImage> images, int index);
}
}

@ -40,9 +40,15 @@ public class BoardActivity extends Activity {
ThemeHelper.getInstance().reloadPostViewColors(this);
rootNavigationController = new RootNavigationController(this, new BrowseController(this));
rootNavigationController = new RootNavigationController(this);
rootNavigationController.onCreate();
setContentView(rootNavigationController.view);
rootNavigationController.pushController(new BrowseController(this), false);
rootNavigationController.onShow();
// Prevent overdraw
// Do this after setContentView, or the decor creating will reset the background to a default non-null drawable
getWindow().setBackgroundDrawable(null);

@ -32,6 +32,7 @@ import org.floens.chan.controller.Controller;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.model.Board;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.PostImage;
import org.floens.chan.ui.layout.ThreadLayout;
import org.floens.chan.ui.toolbar.ToolbarMenu;
import org.floens.chan.ui.toolbar.ToolbarMenuItem;
@ -146,6 +147,11 @@ public class BrowseController extends Controller implements ToolbarMenuItem.Tool
navigationController.pushController(viewThreadController);
}
@Override
public void showImages(List<PostImage> images, int index) {
}
@Override
public void onBoardsChanged() {
loadBoards();

@ -66,10 +66,11 @@ public class PassSettingsController extends Controller implements View.OnClickLi
AndroidUtils.waitForLayout(view, new AndroidUtils.OnMeasuredCallback() {
@Override
public void onMeasured(View view) {
public boolean onMeasured(View view) {
crossfadeView.getLayoutParams().height = crossfadeView.getHeight();
crossfadeView.requestLayout();
crossfadeView.toggle(!loggedIn, false);
return true;
}
});
}
@ -82,7 +83,7 @@ public class PassSettingsController extends Controller implements View.OnClickLi
crossfadeView.toggle(true, true);
button.setText(R.string.setting_pass_login);
hideError();
((PassSettingControllerListener) navigationController.getPreviousSibling(PassSettingsController.this)).onPassEnabledChanged(false);
((PassSettingControllerListener) previousSibling).onPassEnabledChanged(false);
} else {
auth();
}
@ -123,7 +124,7 @@ public class PassSettingsController extends Controller implements View.OnClickLi
button.setText(R.string.setting_pass_logout);
ChanSettings.passId.set(response.passId);
authenticated.setText(response.message);
((PassSettingControllerListener) navigationController.getPreviousSibling(PassSettingsController.this)).onPassEnabledChanged(true);
((PassSettingControllerListener) previousSibling).onPassEnabledChanged(true);
}
button.setEnabled(true);

@ -21,11 +21,9 @@ import android.content.Context;
import android.content.res.Configuration;
import android.support.v4.widget.DrawerLayout;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.controller.NavigationController;
import org.floens.chan.ui.toolbar.Toolbar;
import org.floens.chan.utils.AndroidUtils;
@ -33,8 +31,13 @@ import org.floens.chan.utils.AndroidUtils;
import static org.floens.chan.utils.AndroidUtils.dp;
public class RootNavigationController extends NavigationController {
public RootNavigationController(Context context, Controller startController) {
super(context, startController);
public RootNavigationController(Context context) {
super(context);
}
@Override
public void onCreate() {
super.onCreate();
view = inflateRes(R.layout.root_layout);
toolbar = (Toolbar) view.findViewById(R.id.toolbar);
@ -44,7 +47,12 @@ public class RootNavigationController extends NavigationController {
toolbar.setCallback(this);
initWithController(startController);
AndroidUtils.waitForMeasure(drawer, new AndroidUtils.OnMeasuredCallback() {
@Override
public boolean onMeasured(View view) {
return setDrawerWidth();
}
});
}
@Override
@ -53,17 +61,12 @@ public class RootNavigationController extends NavigationController {
AndroidUtils.waitForLayout(drawer, new AndroidUtils.OnMeasuredCallback() {
@Override
public void onMeasured(View view) {
setDrawerWidth();
public boolean onMeasured(View view) {
return setDrawerWidth();
}
});
}
@Override
public void onCreate() {
setDrawerWidth();
}
@Override
public void onMenuClicked() {
super.onMenuClicked();
@ -71,12 +74,14 @@ public class RootNavigationController extends NavigationController {
drawerLayout.openDrawer(drawer);
}
private void setDrawerWidth() {
private boolean setDrawerWidth() {
int width = Math.min(view.getWidth() - dp(56), dp(56) * 6);
if (drawer.getWidth() != width) {
ViewGroup.LayoutParams params = drawer.getLayoutParams();
params.width = width;
drawer.setLayoutParams(params);
drawer.getLayoutParams().width = width;
drawer.requestLayout();
return true;
} else {
return false;
}
}
}

@ -24,8 +24,11 @@ import android.content.DialogInterface;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.PostImage;
import org.floens.chan.ui.layout.ThreadLayout;
import java.util.List;
public class ViewThreadController extends Controller implements ThreadLayout.ThreadLayoutCallback {
private ThreadLayout threadLayout;
private Loadable loadable;
@ -68,4 +71,9 @@ public class ViewThreadController extends Controller implements ThreadLayout.Thr
.setMessage("/" + threadLoadable.board + "/" + threadLoadable.no)
.show();
}
@Override
public void showImages(List<PostImage> images, int index) {
}
}

@ -62,7 +62,7 @@ public class WatchSettingsController extends SettingsController implements Compo
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ChanSettings.watchEnabled.set(isChecked);
((WatchSettingControllerListener) navigationController.getPreviousSibling(this)).onWatchEnabledChanged(isChecked);
((WatchSettingControllerListener) previousSibling).onWatchEnabledChanged(isChecked);
crossfadeView.toggle(isChecked, true);
}

@ -28,6 +28,7 @@ import android.widget.Toast;
import com.android.volley.VolleyError;
import org.floens.chan.R;
import org.floens.chan.core.model.PostImage;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable;
@ -161,6 +162,11 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
postPopupHelper.showPosts(forPost, posts);
}
@Override
public void showImages(List<PostImage> images, int index) {
callback.showImages(images, index);
}
private void switchVisible(boolean visible) {
if (this.visible != visible) {
this.visible = visible;
@ -170,5 +176,7 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
public interface ThreadLayoutCallback {
public void openThread(Loadable threadLoadable);
public void showImages(List<PostImage> images, int index);
}
}

@ -42,8 +42,9 @@ public class SettingsController extends Controller implements AndroidUtils.OnMea
}
@Override
public void onMeasured(View view) {
public boolean onMeasured(View view) {
setMargins();
return true;
}
public void onPreferenceChange(SettingView item) {

@ -79,8 +79,9 @@ public class Toolbar extends LinearLayout implements View.OnClickListener {
if (item.menu != null) {
AndroidUtils.waitForMeasure(this, new AndroidUtils.OnMeasuredCallback() {
@Override
public void onMeasured(View view) {
public boolean onMeasured(View view) {
setNavigationItemView(animate, pushing, item);
return true;
}
});
} else {
@ -96,7 +97,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener {
public void onClick(View v) {
if (v == arrowMenuView) {
if (callback != null) {
callback.onMenuBackClicked(arrowMenuDrawable.getProgress() == 1f);
callback.onMenuOrBackClicked(arrowMenuDrawable.getProgress() == 1f);
}
}
}
@ -251,10 +252,11 @@ public class Toolbar extends LinearLayout implements View.OnClickListener {
AndroidUtils.waitForMeasure(titleView, new AndroidUtils.OnMeasuredCallback() {
@Override
public void onMeasured(View view) {
public boolean onMeasured(View view) {
if (item.middleMenu != null) {
item.middleMenu.setPopupWidth(Math.max(dp(150), titleView.getWidth()));
}
return false;
}
});
@ -262,6 +264,6 @@ public class Toolbar extends LinearLayout implements View.OnClickListener {
}
public interface ToolbarCallback {
public void onMenuBackClicked(boolean isArrow);
public void onMenuOrBackClicked(boolean isArrow);
}
}

@ -170,7 +170,7 @@ public class AndroidUtils {
}
public interface OnMeasuredCallback {
void onMeasured(View view);
boolean onMeasured(View view);
}
/**
@ -201,13 +201,14 @@ public class AndroidUtils {
observer.removeOnPreDrawListener(this);
}
boolean ret = false;
try {
callback.onMeasured(view);
ret = callback.onMeasured(view);
} catch (Exception e) {
Log.i("AndroidUtils", "Exception in onMeasured", e);
}
return true;
return ret;
}
});
}
@ -239,4 +240,12 @@ public class AndroidUtils {
return views;
}
public static boolean removeFromParentView(View view) {
if (view.getParent() instanceof ViewGroup) {
((ViewGroup) view.getParent()).removeView(view);
return true;
} else {
return false;
}
}
}

Loading…
Cancel
Save