Android: extend Linearlayout, but need same for RelativeLayout. Duplicate code unavoidable? - java

I have this code:
public class CopyOfLinearLayoutEntry extends LinearLayout implements Checkable {
private CheckedTextView _checkbox;
private Context c;
public CopyOfLinearLayoutEntry(Context context) {
super(context);
this.c = context;
setWillNotDraw(false);
}
public CopyOfLinearLayoutEntry(Context context, AttributeSet attrs) {
super(context, attrs);
this.c = context;
setWillNotDraw(false);
}
#Override
protected void onDraw(Canvas canvas) {
Paint strokePaint = new Paint();
strokePaint.setARGB(200, 255, 230, 230);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(12);
Rect r = canvas.getClipBounds();
Rect outline = new Rect(1, 1, r.right - 1, r.bottom - 1);
canvas.drawLine(r.left, r.top, r.right, r.top, strokePaint);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
// find checked text view
int childCount = getChildCount();
for (int i = 0; i < childCount; ++i) {
View v = getChildAt(i);
if (v instanceof CheckedTextView) {
_checkbox = (CheckedTextView) v;
}
}
}
#Override
public boolean isChecked() {
return _checkbox != null ? _checkbox.isChecked() : false;
}
#Override
public void setChecked(boolean checked) {
if (_checkbox != null) {
_checkbox.setChecked(checked);
}
}
#Override
public void toggle() {
if (_checkbox != null) {
_checkbox.toggle();
}
}
}
Now I also need a version for RelativeLayout, so I would duplicate the class file and replace "extends LinearLayout" with "extends RelativeLayout". I think that would be bad, because I do not want any duplicate code.
How would I go about achieving my goal, seeing that Java does not allow multiple inheritance?
I read something about the composition design pattern, but I am not sure how to implement that.
Maybe someone could give me a starting point as to how to most elegantly solve this problem?

You don't need to extend both to avoid duplicate code. You can do something like this:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckedTextView;
public class GenericLayout extends ViewGroup{
private CheckedTextView _checkbox;
public GenericLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
Paint strokePaint = new Paint();
strokePaint.setARGB(200, 255, 230, 230);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(12);
Rect r = canvas.getClipBounds();
Rect outline = new Rect(1, 1, r.right - 1, r.bottom - 1);
canvas.drawLine(r.left, r.top, r.right, r.top, strokePaint);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
// find checked text view
int childCount = getChildCount();
for (int i = 0; i < childCount; ++i) {
View v = getChildAt(i);
if (v instanceof CheckedTextView) {
_checkbox = (CheckedTextView) v;
}
}
}
public boolean isChecked() {
return _checkbox != null ? _checkbox.isChecked() : false;
}
public void setChecked(boolean checked) {
if (_checkbox != null) {
_checkbox.setChecked(checked);
}
}
public void toggle() {
if (_checkbox != null) {
_checkbox.toggle();
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
public class Linear extends LinearLayout {
GenericLayout generic;
public Linear(Context context) {
super(context);
// TODO Auto-generated constructor stub
generic = new GenericLayout(context);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
generic.onDraw(canvas);
}
...
}
public class Relative extends RelativeLayout{
GenericLayout generic;
public Relative(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
generic.onDraw(canvas);
}
...
}

Of what I have learned and been using, there are two ways:
You can do what you are trying to avoid (duplicate the class file and replace "extends LinearLayout" with "extends RelativeLayout")
You can create 2 interfaces and 1 class: One interface that extends LinearLayout, another one for extending RelativeLayout and the class implementing the methods and variables of the extending interfaces.
I hope that helps a little

You have to rethink your approach.
Seems like you are are using layout to control VIEW logic. Unfortunately your question does not have too much information about what you are trying to achieve.
You have few possibilities:
implement LAYOUT proxy / delegate with the custom logic (bad approach IMO)
make a dedicated HANDLER class to control your VIEW objects... these will be independent on the LAYOUT
make your VIEW object and use VIEW object instead of LAYOUT (probably the way to go)

Related

Hide element when AutoCompleteTextView gain focus

I have 3 AutoCompleteTextView and I want to make a simple function to detect whenever it gain/loses focus so I'll hide an imageView.
Or maybe, whenever the keyboard is UP I want to hide my logo (imageView). When the keyboard is down, show the imageView again.
Code so far:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
RelativeLayout layout = (RelativeLayout)findViewById(R.id.mainLayout);
for(int i=0; i< layout.getChildCount(); i++) {
View v = layout.getChildAt(i);
if(v instanceof AutoCompleteTextView) {
v.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
// if(hasWindowFocus()) {
// ImageView logo = findViewById(R.id.imgLogo);
// logo.setVisibility(View.GONE);
// }
Toast.makeText(getApplicationContext(), "pimba", Toast.LENGTH_LONG).show();
}
});
}
}
}
Also, is it possible to create listeners outside this onCreate() ? Or creating everything inside this function is the right way to go?
Try this
Solution 1
Call this method in onCreate()
private void initKeyBoardListener() {
//Threshold for minimal keyboard height.
final int MIN_KEYBOARD_HEIGHT_PX = 150;
//Top-level window decor view.
final View decorView = getWindow().getDecorView();
// Register global layout listener.
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
// Retrieve visible rectangle inside window.
private final Rect windowVisibleDisplayFrame = new Rect();
private int lastVisibleDecorViewHeight;
#Override
public void onGlobalLayout() {
decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);
final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();
if (lastVisibleDecorViewHeight != 0) {
if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {
Log.d("Keyboard", "SHOW");
// Hide imageview
} else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {
// Show imageview
Log.d("Keyboard", "HIDE");
}
}
// Save current decor view height for the next call.
lastVisibleDecorViewHeight = visibleDecorViewHeight;
}
});
}
Solution 2
Use this Util class
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import java.util.HashMap;
/**
* Created by Raman on 2/10/2017.
*/
public class KeyboardUtils implements ViewTreeObserver.OnGlobalLayoutListener {
private static HashMap<SoftKeyboardToggleListener, KeyboardUtils> sListenerMap = new HashMap<>();
private SoftKeyboardToggleListener mCallback;
private View mRootView;
private float mScreenDensity = 1;
private KeyboardUtils(Activity act, SoftKeyboardToggleListener listener) {
mCallback = listener;
mRootView = ((ViewGroup) act.findViewById(android.R.id.content)).getChildAt(0);
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
mScreenDensity = act.getResources().getDisplayMetrics().density;
}
public static void addKeyboardToggleListener(Activity act, SoftKeyboardToggleListener listener) {
removeKeyboardToggleListener(listener);
sListenerMap.put(listener, new KeyboardUtils(act, listener));
}
public static void removeKeyboardToggleListener(SoftKeyboardToggleListener listener) {
if (sListenerMap.containsKey(listener)) {
KeyboardUtils k = sListenerMap.get(listener);
k.removeListener();
sListenerMap.remove(listener);
}
}
public static void removeAllKeyboardToggleListeners() {
for (SoftKeyboardToggleListener l : sListenerMap.keySet())
sListenerMap.get(l).removeListener();
sListenerMap.clear();
}
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
mRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
float dp = heightDiff / mScreenDensity;
if (mCallback != null)
mCallback.onToggleSoftKeyboard(dp > 200);
}
private void removeListener() {
mCallback = null;
mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
public interface SoftKeyboardToggleListener {
void onToggleSoftKeyboard(boolean isVisible);
}
}
And its usage
Call this in onCreate()
KeyboardUtils.addKeyboardToggleListener(getActivity(), new KeyboardUtils.SoftKeyboardToggleListener() {
#Override
public void onToggleSoftKeyboard(boolean isVisible) {
Log.d("keyboard", "keyboard visible: " + isVisible);
if (!isVisible) {
// show imageview
}
else
{
// hide imageview
}
}
});

How to swipe zoomed image using ImageViews and PageAdapter

I am trying to create an image viewer which can load images from given URLs.The code below implement the User Interface.
My intention is to let user Zoom the image and move to next image with a Swipe event.But the problem is that when i zoom and then swipe , instead of showing the remaining portion , it moves to the next image.
I tried using requestDisallowInterceptTouchEvent in TouchImageView's(https://github.com/MikeOrtiz/TouchImageView) onTouchListener .After this the remaining portion could show but now i cannot go to the next page. I was wondering how this can be achieved as the event can only go to either TouchView or PageAdapter
public class PageActivity extends Activity {
private int numPages = 33;
private TouchImageView[] imageViews = new TouchImageView[numPages];
private String URL = "http://www.smbc-comics.com/comics/200905";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewPager viewPager = new ViewPager(this);
for (int i = 0; i < numPages; i++) {
imageViews[i] = new TouchImageView(this);
imageViews[i].setBackgroundResource(R.drawable.banke);
imageViews[i].setMaxZoom(4f);
}
setContentView(viewPager);
ImagePagerAdapter adapter = new ImagePagerAdapter();
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
}
#SuppressWarnings("unused")
private class ImagePagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return numPages;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((TouchImageView) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Context context = PageActivity.this;
String pageURL = URL;
if (imageViews[position].getDrawable() == null) {
ImageFetcher imagefetcher = new ImageFetcher();
imagefetcher.execute(
pageURL + String.format("%02d", position+1) + ".gif",
String.valueOf(position));
}
((ViewPager) container).addView(imageViews[position], 0);
return imageViews[position];
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((TouchImageView) object);
imageViews[position].setImageDrawable(null);
}
}
public class ImageFetcher extends AsyncTask<String, Integer, Drawable> {
int fillthisPos;
public Drawable doInBackground(String... urls) {
try {
InputStream is = (InputStream) new URL(urls[0]).getContent();
fillthisPos = Integer.parseInt(urls[1]);
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(Drawable result) {
super.onPostExecute(result);
imageViews[fillthisPos].setImageDrawable(result);
result = null;
}
}
}
You can add following code in TouchImageView class:
public boolean isZoomed () {
return (normalizedScale > minScale);
}
private void onSwipeEvent(MotionEvent event) {
boolean zoomed = this.isZoomed();
if (!zoomed && (swipeLen > 0)) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
swipeStartPos = (int) event.getRawX();
}
else if (event.getAction() == MotionEvent.ACTION_MOVE) {
int distance = ((int) event.getRawX()) - swipeStartPos;
int swipeVector = SWIPE_RIGHT;
if (distance < 0) swipeVector = SWIPE_LEFT;
if (Math.abs(distance) > swipeLen) {
onSwipeHandler.onSwipe(swipeVector);
swipeStartPos = (int) event.getRawX();
this.setScaleX(1f);
}
else {
int swipeStDist = swipeLen - Math.round(((swipeLen / 100) * 50));
if (Math.abs(distance) > swipeStDist) {
this.setScaleX(0.98f);
}
}
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
swipeStartPos = (int) event.getRawX();
this.setScaleX(1f);
}
}
}
public static int SWIPE_LEFT = 0;
public static int SWIPE_RIGHT = 1;
public int swipeStartPos = 0;
public onSwipeListener onSwipeHandler = new onSwipeListener() {
public void onSwipe(int vector) {}
};
public static int swipeLen = 0;
public void setOnSwipeListener(onSwipeListener c, int swipeLength) {
onSwipeHandler = c;
swipeLen = swipeLength;
}
public interface onSwipeListener {
public void onSwipe(int vector);
}
And also in TouchImageView below line 636 add onSwipeEvent(event) like this:
......
setImageMatrix(matrix);
onSwipeEvent(event);
//
// indicate event was handled
//
return true;
...........
After this from you code you can add swipe event listener, like this:
imageView.setOnSwipeListener(new TouchImageView.onSwipeListener() {
#Override
public void onSwipe(int vector) {
if (vector == TouchImageView.SWIPE_LEFT) {
Log.d("swipe", "swipe left!");
}
else if (vector == TouchImageView.SWIPE_RIGHT) {
Log.d("swipe", "swipe right!");
}
}
}, 200); //length of swiping - 200 dip
This onSwipeListener ignore onswipe where image is zoomed+. It work for me.

Caused by: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.slidingmenu.lib.SlidingMenu

I've just read all questions about this problem at stackoverflow and some forums, but still have no solution. I tried to remove R.java, clear the cache, edit .xml but nothing helps.
Error text:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.easyten.app/com.easyten.app.EasyTenActivity}:
java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.slidingmenu.lib.SlidingMenu ...
Caused by: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.slidingmenu.lib.SlidingMenu
at com.slidingmenu.lib.app.SlidingActivityHelper.onCreate(SlidingActivityHelper.java:32)
This is the code:
slidingmenumain.xml
<?xml version="1.0" encoding="utf-8"?>
<com.slidingmenu.lib.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/slidingmenumain"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
SlidingActivityHelper.java
package com.slidingmenu.lib.app;
import android.app.Activity;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import com.slidingmenu.lib.R;
import com.slidingmenu.lib.SlidingMenu;
public class SlidingActivityHelper {
private Activity mActivity;
private SlidingMenu mSlidingMenu;
private View mViewAbove;
private View mViewBehind;
private boolean mBroadcasting = false;
private boolean mOnPostCreateCalled = false;
private boolean mEnableSlide = true;
public SlidingActivityHelper(Activity activity) {
mActivity = activity;
}
public void onCreate(Bundle savedInstanceState) {
mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.slidingmenumain, null);
}
...other code
}
32 line of SlidingActivityHelper.java is mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.slidingmenumain, null);
SlidingMenu.java
package com.slidingmenu.lib;
import java.lang.reflect.Method;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.slidingmenu.lib.CustomViewAbove.OnPageChangeListener;
public class SlidingMenu extends RelativeLayout {
public static final int TOUCHMODE_MARGIN = 0;
public static final int TOUCHMODE_FULLSCREEN = 1;
private CustomViewAbove mViewAbove;
private CustomViewBehind mViewBehind;
private OnOpenListener mOpenListener;
private OnCloseListener mCloseListener;
//private boolean mSlidingEnabled;
public static void attachSlidingMenu(Activity activity, SlidingMenu sm, boolean slidingTitle) {
if (sm.getParent() != null)
throw new IllegalStateException("SlidingMenu cannot be attached to another view when" +
" calling the static method attachSlidingMenu");
if (slidingTitle) {
// get the window background
TypedArray a = activity.getTheme().obtainStyledAttributes(new int[] {android.R.attr.windowBackground});
int background = a.getResourceId(0, 0);
// move everything into the SlidingMenu
ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
decor.removeAllViews();
// save ActionBar themes that have transparent assets
decorChild.setBackgroundResource(background);
sm.setContent(decorChild);
decor.addView(sm);
} else {
// take the above view out of
ViewGroup content = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
View above = content.getChildAt(0);
content.removeAllViews();
sm.setContent(above);
content.addView(sm, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
}
public interface OnOpenListener {
public void onOpen();
}
public interface OnOpenedListener {
public void onOpened();
}
public interface OnCloseListener {
public void onClose();
}
public interface OnClosedListener {
public void onClosed();
}
public interface CanvasTransformer {
public void transformCanvas(Canvas canvas, float percentOpen);
}
public SlidingMenu(Context context) {
this(context, null);
}
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mViewBehind = new CustomViewBehind(context);
addView(mViewBehind, behindParams);
LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mViewAbove = new CustomViewAbove(context);
addView(mViewAbove, aboveParams);
// register the CustomViewBehind2 with the CustomViewAbove
mViewAbove.setCustomViewBehind(mViewBehind);
mViewBehind.setCustomViewAbove(mViewAbove);
mViewAbove.setOnPageChangeListener(new OnPageChangeListener() {
public static final int POSITION_OPEN = 0;
public static final int POSITION_CLOSE = 1;
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) { }
public void onPageSelected(int position) {
if (position == POSITION_OPEN && mOpenListener != null) {
mOpenListener.onOpen();
} else if (position == POSITION_CLOSE && mCloseListener != null) {
mCloseListener.onClose();
}
}
});
// now style everything!
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu);
// set the above and behind views if defined in xml
int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1);
if (viewAbove != -1)
setContent(viewAbove);
int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1);
if (viewBehind != -1)
setMenu(viewBehind);
int touchModeAbove = ta.getInt(R.styleable.SlidingMenu_aboveTouchMode, TOUCHMODE_MARGIN);
setTouchModeAbove(touchModeAbove);
int touchModeBehind = ta.getInt(R.styleable.SlidingMenu_behindTouchMode, TOUCHMODE_MARGIN);
setTouchModeBehind(touchModeBehind);
int offsetBehind = (int) ta.getDimension(R.styleable.SlidingMenu_behindOffset, -1);
int widthBehind = (int) ta.getDimension(R.styleable.SlidingMenu_behindWidth, -1);
if (offsetBehind != -1 && widthBehind != -1)
throw new IllegalStateException("Cannot set both behindOffset and behindWidth for a SlidingMenu");
else if (offsetBehind != -1)
setBehindOffset(offsetBehind);
else if (widthBehind != -1)
setBehindWidth(widthBehind);
else
setBehindOffset(0);
float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.33f);
setBehindScrollScale(scrollOffsetBehind);
int shadowRes = ta.getResourceId(R.styleable.SlidingMenu_shadowDrawable, -1);
if (shadowRes != -1) {
setShadowDrawable(shadowRes);
}
int shadowWidth = (int) ta.getDimension(R.styleable.SlidingMenu_shadowWidth, 0);
setShadowWidth(shadowWidth);
boolean fadeEnabled = ta.getBoolean(R.styleable.SlidingMenu_behindFadeEnabled, true);
setFadeEnabled(fadeEnabled);
float fadeDeg = ta.getFloat(R.styleable.SlidingMenu_behindFadeDegree, 0.66f);
setFadeDegree(fadeDeg);
boolean selectorEnabled = ta.getBoolean(R.styleable.SlidingMenu_selectorEnabled, false);
setSelectorEnabled(selectorEnabled);
int selectorRes = ta.getResourceId(R.styleable.SlidingMenu_selectorDrawable, -1);
if (selectorRes != -1)
setSelectorDrawable(selectorRes);
}
public void setContent(int res) {
setContent(LayoutInflater.from(getContext()).inflate(res, null));
}
public void setContent(View v) {
mViewAbove.setContent(v);
mViewAbove.invalidate();
showAbove(true);
}
public void setMenu(int res) {
setMenu(LayoutInflater.from(getContext()).inflate(res, null));
}
public void setMenu(View v) {
mViewBehind.setMenu(v);
mViewBehind.invalidate();
}
public void setSlidingEnabled(boolean b) {
mViewAbove.setSlidingEnabled(b);
}
public boolean isSlidingEnabled() {
return mViewAbove.isSlidingEnabled();
}
/**
*
* #param b Whether or not the SlidingMenu is in a static mode
* (i.e. nothing is moving and everything is showing)
*/
public void setStatic(boolean b) {
if (b) {
setSlidingEnabled(false);
mViewAbove.setCustomViewBehind(null);
mViewAbove.setCurrentItem(1);
mViewBehind.setCurrentItem(0);
} else {
mViewAbove.setCurrentItem(1);
mViewBehind.setCurrentItem(1);
mViewAbove.setCustomViewBehind(mViewBehind);
setSlidingEnabled(true);
}
}
/**
* Shows the behind view
*/
public void showBehind(boolean b) {
mViewAbove.setCurrentItem(0, b);
}
public void showBehind() {
mViewAbove.setCurrentItem(0);
}
/**
* Shows the above view
*/
public void showAbove(boolean b) {
mViewAbove.setCurrentItem(1, b);
}
public void showAbove() {
mViewAbove.setCurrentItem(1);
}
/**
*
* #return Whether or not the behind view is showing
*/
public boolean isBehindShowing() {
return mViewAbove.getCurrentItem() == 0;
}
/**
*
* #return The margin on the right of the screen that the behind view scrolls to
*/
public int getBehindOffset() {
return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin;
}
/**
*
* #param i The margin on the right of the screen that the behind view scrolls to
*/
public void setBehindOffset(int i) {
RelativeLayout.LayoutParams params = ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams());
int bottom = params.bottomMargin;
int top = params.topMargin;
int left = params.leftMargin;
params.setMargins(left, top, i, bottom);
}
/**
*
* #param i The width the Sliding Menu will open to in pixels
*/
#SuppressWarnings("deprecation")
public void setBehindWidth(int i) {
int width;
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
try {
Class<?> cls = Display.class;
Class<?>[] parameterTypes = {Point.class};
Point parameter = new Point();
Method method = cls.getMethod("getSize", parameterTypes);
method.invoke(display, parameter);
width = parameter.x;
} catch (Exception e) {
width = display.getWidth();
}
setBehindOffset(width-i);
}
/**
*
* #param res A resource ID which points to the width the Sliding Menu will open to
*/
public void setBehindWidthRes(int res) {
int i = (int) getContext().getResources().getDimension(res);
setBehindWidth(i);
}
/**
*
* #param res The dimension resource to be set as the behind offset
*/
public void setBehindOffsetRes(int res) {
int i = (int) getContext().getResources().getDimension(res);
setBehindOffset(i);
}
/**
*
* #return The scale of the parallax scroll
*/
public float getBehindScrollScale() {
return mViewAbove.getScrollScale();
}
/**
*
* #param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every
* 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels)
*/
public void setBehindScrollScale(float f) {
mViewAbove.setScrollScale(f);
}
public void setBehindCanvasTransformer(CanvasTransformer t) {
mViewBehind.setCanvasTransformer(t);
}
public int getTouchModeAbove() {
return mViewAbove.getTouchMode();
}
public void setTouchModeAbove(int i) {
if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN) {
throw new IllegalStateException("TouchMode must be set to either" +
"TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN.");
}
mViewAbove.setTouchMode(i);
}
public int getTouchModeBehind() {
return mViewBehind.getTouchMode();
}
public void setTouchModeBehind(int i) {
if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN) {
throw new IllegalStateException("TouchMode must be set to either" +
"TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN.");
}
mViewBehind.setTouchMode(i);
}
public void setShadowDrawable(int resId) {
mViewAbove.setShadowDrawable(resId);
}
public void setShadowWidthRes(int resId) {
setShadowWidth((int)getResources().getDimension(resId));
}
public void setShadowWidth(int pixels) {
mViewAbove.setShadowWidth(pixels);
}
public void setFadeEnabled(boolean b) {
mViewAbove.setBehindFadeEnabled(b);
}
public void setFadeDegree(float f) {
mViewAbove.setBehindFadeDegree(f);
}
public void setSelectorEnabled(boolean b) {
mViewAbove.setSelectorEnabled(true);
}
public void setSelectedView(View v) {
mViewAbove.setSelectedView(v);
}
public void setSelectorDrawable(int res) {
mViewAbove.setSelectorDrawable(BitmapFactory.decodeResource(getResources(), res));
}
public void setSelectorDrawable(Bitmap b) {
mViewAbove.setSelectorDrawable(b);
}
public void setOnOpenListener(OnOpenListener listener) {
//mViewAbove.setOnOpenListener(listener);
mOpenListener = listener;
}
public void setOnCloseListener(OnCloseListener listener) {
//mViewAbove.setOnCloseListener(listener);
mCloseListener = listener;
}
public void setOnOpenedListener(OnOpenedListener listener) {
mViewAbove.setOnOpenedListener(listener);
}
public void setOnClosedListener(OnClosedListener listener) {
mViewAbove.setOnClosedListener(listener);
}
private static class SavedState extends BaseSavedState {
boolean mBehindShowing;
public SavedState(Parcelable superState) {
super(superState);
}
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeBooleanArray(new boolean[]{mBehindShowing});
}
/*
public static final Parcelable.Creator<SavedState> CREATOR
= ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {
public SavedState createFromParcel(Parcel in, ClassLoader loader) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
});
SavedState(Parcel in) {
super(in);
boolean[] showing = new boolean[1];
in.readBooleanArray(showing);
mBehindShowing = showing[0];
}
*/
}
#Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.mBehindShowing = isBehindShowing();
return ss;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
if (ss.mBehindShowing) {
showBehind(true);
} else {
showAbove(true);
}
}
#Override
protected boolean fitSystemWindows(Rect insets) {
int leftPadding = getPaddingLeft() + insets.left;
int rightPadding = getPaddingRight() + insets.right;
int topPadding = insets.top;
int bottomPadding = insets.bottom;
this.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
return super.fitSystemWindows(insets);
}
}
What's wrong? How can I fix it? I'm using IntelliJ IDEA 12 CE. Thanks a lot for any help!
This can be resolved by recreating the R.java file.
1. Re-build OR
2. Change the 'android:id' in XML file to a new id and re-build. Make sure you manually change all references to this id.
Sometimes this does´t work even recreating the R.java file, cleaning and rebuilding the project.
for me it works until i delete \gen and \bin folders, then automatically were recreated with the new relationship between resources and their id´s.
I think the problem is just that the inflater cast your item to RelativeLayout and you can't cast a relativeLayout in your item (Maybe this post is more precise : ClassCastException). Perhaps you have to give up and retrieve your object using your id with findViewById.

custom ondraw method is not working

I am working on application in which i want to display different text on image.when i touch the different position.I am working on the different image.In my program I have used one class to change the image and one class to draw a text on the image.
my activity class is as follow......
public class VideosActivity extends Activity implements OnTouchListener
{
//DrawView draw;
float a=0;
float b=0;
ImageView image;
MotionEvent event;
Button back ;
Button next;
TextView t;
String info = "";
int count =0;
FirstImage i;
ViewFlipper c;
Infoview v;
String huma="human";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.videos_layout);
i=new FirstImage(this);
c=(ViewFlipper) findViewById(R.id.viewFlipper1);
back = (Button) findViewById(R.id.button1);
next = (Button) findViewById(R.id.button2);
t=(TextView) findViewById(R.id.textView1);
if(count==0)
i.changeImage(R.drawable.human );
i.invalidate();
c.addView(i,0);
c.setOnTouchListener(this);
c.onTouchEvent(event);
}
public void pageinfo(float a,float b)
{
t.setText(Float.toString(a)+"x"+Float.toString(b)+"y");
i.display( a, b);
}
public boolean onTouch(View v, MotionEvent me)
{
// TODO Auto-generated method stub
switch(me.getAction())
{
case MotionEvent.ACTION_DOWN:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
case MotionEvent.ACTION_MOVE:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
case MotionEvent.ACTION_UP:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
case MotionEvent.ACTION_OUTSIDE:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
default: return false;
}
return true;
}
}
the class which is used to change the image is as follow...
public class FirstImage extends LinearLayout {
ImageView i;
int x;
Infoview v;
String huma ="human";
public FirstImage(Context context) {
super(context);
v=new Infoview(context);
i= new ImageView (context);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
addView(i, lp);
addView(v,lp);
}
public FirstImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void changeImage(int id){
i.setImageResource(id);
x=id;
}
public int getSrc() {
// TODO Auto-generated method stub
return x;
}
public void display(float a, float b) {
// TODO Auto-generated method stub
if(i.getId()==R.drawable.human){
v.updateInfo(huma, a, b);
i.invalidate();
v.invalidate();
}
}
}
class which is used for drawing text on the image is as follow..
public class Infoview extends View {
String info = "";
float x = 0; //init value
float y = 0; //init value
int color = Color.WHITE;
public Infoview(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public Infoview(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public Infoview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(color);
paint.setStrokeWidth(2);
paint.setTextSize(30);
canvas.drawLine(x-10, y, x+10, y, paint);
canvas.drawLine(x, y-10, x, y+10, paint);
canvas.drawText(info, x, y, paint);
}
public void updateInfo(String t_info, float t_x, float t_y){
info = t_info;
x = t_x;
y = t_y;
invalidate();
}
public void clearInfo(){
info = "";
x = 0;
y = 0;
invalidate();
}
I am not understanding why it is not displaying text on the image ......I think in the time of image drawing i am using one layout.so i have to include drawing class(Infoview) into that layout to...
If any one thinking that i am re asking this question then i am sorry ...
any help is appreciated...
I did get time to read the full code but if you override onDraw, you are not supposed to invoke super.onDraw() inside that method since that will mean that the base class will draw everything first.

Can I extend the Overlay class?

I have created a class that extends the Overlay class in Osmdroid (CustomOverlay.java). However, nothing appear on the map after I call the method createMark() on the main activity which make use of CustomOverlay.java. I do not want to use ItemizedOverlay class.
Any idea?
CustomOverlay.java (class that extends Overlay)
public CustomOverlay(Context context) {
super(context);
}
#Override
protected void draw(Canvas canvas, MapView mapView, boolean shadow) {
Point screenPoint = new Point();
mapView.getProjection().toPixels(geoPoint, screenPoint);
super.drawAt(canvas, mapView.getResources().getDrawable(R.drawable.marker), screenPoint.x, screenPoint.y, shadow);
}
}
This is the method I call in the main activity:
private void createMarker() {
List<Overlay> mapOverlays = mMapView.getOverlays();
Overlay c = new CustomOverlay(this);
mapOverlays.add(c);
mMapView.invalidate();
}
Answer:
#Override
protected void draw(Canvas canvas, MapView mapView, boolean shadow) {
Point screenPoint = new Point();
mapView.getProjection().toPixels(geoPoint, screenPoint);
Bitmap marker= BitmapFactory.decodeResource(mapView.getResources(), R.drawable.marker);
canvas.drawBitmap(marker, screenPoint.x, screenPoint.y, null);
}
Here's the skeleton of a customized overlay:
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
public MyItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
public void removeAllOverlay() {
mOverlays.clear();
}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
}
See the differences? Where is your populate() call?
Hope this helps.

Categories