How do I add a click handler to an ImageCell?
This is what I have:
ImageCell btn= new ImageCell();
Column<Contact,String> column = new Column<Contact,String>(btn)
{
#Override
public String getValue(Contact c)
{
return c.imageLocation;
}
};
column.setFieldUpdater(new FieldUpdater<Contact,String>()
{
public void update(int index, Contact c, String value)
{
Window.alert("clicked");
}
});
This works as well.
// clickable imageresource cell
public class ClickableImageResourceCell extends AbstractCell<ImageResource> {
private static ImageResourceRenderer renderer;
public ClickableImageResourceCell () {
super(BrowserEvents.CLICK);
if (renderer == null) {
renderer = new ImageResourceRenderer();
}
}
#Override
public void onBrowserEvent(Context context, final Element parent, ImageResource value, NativeEvent event,
ValueUpdater<ImageResource> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if (BrowserEvents.CLICK.equals(event.getType())) {
onEnterKeyDown(context, parent, value, event, valueUpdater);
}
}
#Override
public void render(com.google.gwt.cell.client.Cell.Context context,
ImageResource value, final SafeHtmlBuilder sb) {
sb.append(renderer.render(value));
}
#Override
protected void onEnterKeyDown(Context context, Element parent, ImageResource value, NativeEvent event,
ValueUpdater<ImageResource> valueUpdater) {
if (valueUpdater != null) {
valueUpdater.update(value);
}
}
}
Maybe this helps: Adding clickHandler to row in CellTable in GWT?. It's not a clickhandler on the cell, but on the cell table (or list). which is more efficient.
I resolved this issue by creating my own ButtonCell class. Following is my code:
import com.google.gwt.cell.client.AbstractSafeHtmlCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.text.shared.SafeHtmlRenderer;
import com.google.gwt.text.shared.SimpleSafeHtmlRenderer;
/**
* A {#link Cell} used to render a button.
*/
public class ClickImage extends AbstractSafeHtmlCell<String> {
/**
* Construct a new ButtonCell that will use a {#link SimpleSafeHtmlRenderer}.
*/
private String bgImage="";
public ClickImage()
{
this(SimpleSafeHtmlRenderer.getInstance());
}
public ClickImage(String bgImage)
{
this(SimpleSafeHtmlRenderer.getInstance());
this.bgImage=bgImage;
}
public String getBgImage()
{
return bgImage;
}
public void setBgImage(String bgImage)
{
this.bgImage = bgImage;
}
/**
* Construct a new ButtonCell that will use a given {#link SafeHtmlRenderer}.
*
* #param renderer a {#link SafeHtmlRenderer SafeHtmlRenderer<String>} instance
*/
public ClickImage(SafeHtmlRenderer<String> renderer) {
super(renderer, "click", "keydown");
}
#Override
public void onBrowserEvent(Context context, Element parent, String value,
NativeEvent event, ValueUpdater<String> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType())) {
onEnterKeyDown(context, parent, value, event, valueUpdater);
}
}
#Override
public void render(Context context, SafeHtml data, SafeHtmlBuilder sb)
{
String img=getBgImage();
String disableButton="";
if(img.equals("transparentButton"))
{
disableButton = "disabled=\"disabled\"";
}
sb.appendHtmlConstant("<button class=\""+img+"\" type=\"button\" "+disableButton+" tabindex=\"-1\">");
if (data != null) {
sb.append(data);
}
sb.appendHtmlConstant("</button>");
}
#Override
protected void onEnterKeyDown(Context context, Element parent, String value,
NativeEvent event, ValueUpdater<String> valueUpdater) {
if (valueUpdater != null) {
valueUpdater.update(value);
}
}
}
So I used a button to show the image. I used css to make the background color for the button to be transparent and also, I'm passing the link to the image as a parameter to the constructor when the button is being created, that way I can create different clickable images. This worked for me!
addButtonCell("resources/ui/images/download.png", "Download", "download");
private void addButtonCell(final String imageSrc, String columnName, final String action)
{
ActionCell<AttachmentDTO> imageButtonCell = new ActionCell<AttachmentDTO>("", new Delegate<AttachmentDTO>()
{
#Override
public void execute(final AttachmentDTO object)
{
if(action.equalsIgnoreCase("download"))
{
download(object);
}
else
{
eventBus.fireEvent(new ImgButtonClickEvent(object));
}
}
})
{
#Override
public void render(Context context, AttachmentDTO value, SafeHtmlBuilder sb)
{
Image icon = new Image(imageSrc);
SafeHtmlBuilder builder = new SafeHtmlBuilder();
builder.appendHtmlConstant(icon.toString());
sb.append(builder.toSafeHtml());
}
};
final Column<AttachmentDTO, AttachmentDTO> column = new Column<AttachmentDTO, AttachmentDTO>(imageButtonCell)
{
#Override
public AttachmentDTO getValue(AttachmentDTO object)
{
return object;
}
};
cellTable.addColumn(column, columnName);
column.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
cellTable.setColumnWidth(column, "80px");
}
Related
I've been working on google's course sunshine app and wanted to put my personal touch in it so i made the user specify his city by using a hybrid of EditTextPreference and AutoCompleteTextView shown in here:
public class AutoCompleteEditTextPreference extends EditTextPreference {
private static String[] list;
private boolean isValid = true;
private Dialog dialog;
public AutoCompleteEditTextPreference(Context context) {
super(context);
}
public AutoCompleteEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoCompleteEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* the default EditTextPreference does not make it easy to
* use an AutoCompleteEditTextPreference field. By overriding this method
* we perform surgery on it to use the type of edit field that
* we want.
*/
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
// find the current EditText object
final EditText editText = (EditText) view.findViewById(android.R.id.edit);
// copy its layout params
ViewGroup.LayoutParams params = editText.getLayoutParams();
ViewGroup vg = (ViewGroup) editText.getParent();
String curVal = editText.getText().toString();
// remove it from the existing layout hierarchy
vg.removeView(editText);
// construct a new editable autocomplete object with the appropriate params
// and id that the TextEditPreference is expecting
mACTV = new AutoCompleteTextView(getContext());
mACTV.setLayoutParams(params);
mACTV.setId(android.R.id.edit);
mACTV.setText(curVal);
Arrays.sort(list);
isValid = isValid(mACTV.getText().toString());
mACTV.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
isValid = isValid(s.toString());
validate();
}
});
mACTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
isValid = isValid(mACTV.getText().toString());
validate();
}
});
ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(),
android.R.layout.simple_dropdown_item_1line, list);
mACTV.setAdapter(adapter);
// add the new view to the layout
vg.addView(mACTV);
}
private boolean isValid(CharSequence text) {
return !text.equals("") && Arrays.binarySearch(list, text.toString()) > 0;
}
#Override
protected void showDialog(Bundle state) {
super.showDialog(state);
validate();
}
private void validate() {
dialog = getDialog();
Toast.makeText(getContext(), Boolean.toString(dialog instanceof AlertDialog), Toast.LENGTH_SHORT).show();
if (dialog instanceof AlertDialog) {
Button btn = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
btn.setEnabled(isValid);
}
}
/**
* Because the baseclass does not handle this correctly
* we need to query our injected AutoCompleteTextView for
* the value to save
*/
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult && mACTV != null) {
String value = mACTV.getText().toString();
if (callChangeListener(value))
setText(value);
}
}
static void prepareCountriesList(Context context) {
List<String> lines = new ArrayList<>();
try {
InputStream inputStream = context.getAssets().open("cities.txt");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
list = lines.toArray(new String[lines.size()]);
}
/**
* again we need to override methods from the base class
*/
public EditText getEditText() {
return mACTV;
}
private AutoCompleteTextView mACTV = null;
private final String TAG = "AutoCompleteEditTextPreference";
}
so everything was going great until the last part where i wanted to disable the ok button
private void validate() {
dialog = getDialog();
Toast.makeText(getContext(), Boolean.toString(dialog instanceof AlertDialog), Toast.LENGTH_SHORT).show();
if (dialog instanceof AlertDialog) {
Button btn = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
btn.setEnabled(isValid);
}
}
so i try the method getDialog();
and it returns a dialog that is not null and not an instance of AlertDialog
anyhelp please on getting the dialog properly or another way to disable the ok button programmatically
It's ok found the problem;
it was that i used
import android.support.v7.app.AlertDialog;
instead of
import android.app.AlertDialog;
thanks for anyone who tried to help
This is my ParseRecyclerQueryAdapter :
// Set up a customized query
ParseRecyclerQueryAdapter<PlaceFilters,PhotoFiltersAdapter> mainAdapter = new ParseRecyclerQueryAdapter<>(this, PhotoFiltersAdapter.class
,"PlaceFilters");
public ParseQuery<PlaceFilters> create() {
Location myLoc = (currentLocation == null) ? lastLocation : currentLocation;
ParseQuery<PlaceFilters> query = PlaceFilters.getQuery();
query.include("user");
query.orderByDescending("createdAt");
query.whereWithinKilometers("location", geoPointFromLocation(myLoc), radius);
query.setLimit(6);
return query;
}
This the doListQuery Method in which I want to call loadobjects into RecyclerView when location!=null
/*
* Set up a query to update the list view
*/
private void doListQuery() {
Location myLoc = (currentLocation == null) ? lastLocation : currentLocation;
// If location info is available, load the data
if (myLoc != null) {
// Refreshes the list view with new data based
// usually on updated location data.
}
}
This is the my ViewHolder Class :
public class PhotoFiltersAdapter extends RecyclerView.ViewHolder {
public PhotoFiltersAdapter(View view) {
super(view);
PlaceName = (TextView) view.findViewById(R.id.place_names);
}
#Bind(R.id.place_names)
#ParseName("PlaceName")
public TextView PlaceName;
}
Then my ParseRecyclerQueryAdapter Class :
public class FiltersQueryAdapter extends ParseRecyclerQueryAdapter<PlaceFilters, PhotoFiltersAdapter> {
public FiltersQueryAdapter(Context context, Class clazz,QueryFactory queryFactory) {
super(context, clazz, queryFactory);
}
#Override
public void onBindViewHolder(PhotoFiltersAdapter holder, int position) {
super.onBindViewHolder(holder, position);
holder.PlaceName.setText(object.getString("PlaceName"));
}
}
This is my Parse Objects Class :
#ParseClassName("PlaceFilters")
public class PlaceFilters extends ParseObject{
public String getText() {
return getString("PlaceName");
}
public ParseGeoPoint getLocation() {
return getParseGeoPoint("GeoArea");
}
public static ParseQuery<PlaceFilters> getQuery() {
return ParseQuery.getQuery(PlaceFilters.class);
}
}
I wish to disable the native contextual menu that is shown when you select some text, the one with the select all, copy, share and search buttons. I do not however want to disable selections themselves. Ideally I would wish to extend the menu actually, but honestly, I am more than perfectly fine with just disabling it. With textfields and the like it tends to be relatively simple from the documentation I found, but I just can't figure out a way to make this work with XWalkView/CordovaWebView. Might be that I am just searching in entirely the wrong corner though.
I have a workaround.
For WebView there is a solution, but it doesn't work for XWalkView:
WebView selection menu workaround
My gradle includes compile 'org.xwalk:xwalk_core_library:14.43.343.17'
My solution, the main idea in the onAttachedToWindow method:
public class XWalkWebView extends XWalkView {
public XWalkWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
private ActionMode.Callback mOriginalCallback;
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
try {
View innerChild = ((ViewGroup) getChildAt(0)).getChildAt(0);
Field contentViewField = innerChild.getClass().getDeclaredField("mContentView");
contentViewField.setAccessible(true);
XWalkContentView xWalkContentView = (XWalkContentView) contentViewField.get(innerChild);
Field contentViewCoreField = xWalkContentView.getClass().getSuperclass().getDeclaredField("mContentViewCore");
contentViewCoreField.setAccessible(true);
ContentViewCore viewCore = (ContentViewCore) contentViewCoreField.get(xWalkContentView);
viewCore.setContainerView(this);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
#Override
public ActionMode startActionMode(ActionMode.Callback callback) {
mOriginalCallback = callback;
ActionMode.Callback c = new // your callback...
return super.startActionMode(c);
}
}
I try Warabei's solution but it not work on 15.44.384.13. I improve to find ContentViewCore cross versions:
public class XWalkWebView extends XWalkView {
...
private Field getFields(Class clazz){
for(Field field:clazz.getDeclaredFields()){
if(ContentViewCore.class == field.getType()){
return field;
}
}
clazz = clazz.getSuperclass();
if(clazz!=null && clazz!=Object.class){
Field field = getFields(clazz);
if(field!=null)return field;
}
return null;
}
private void inject(View view){
Field field = getFields(view.getClass());
if(field!=null){
field.setAccessible(true);
try {
ContentViewCore viewCore = (ContentViewCore) field.get(view);
viewCore.setContainerView(this);
return;
}catch(Exception e){
}
}
if(view instanceof ViewGroup){
ViewGroup viewGroup = (ViewGroup)view;
int count = viewGroup.getChildCount();
for(int i = 0;i<count;i++){
inject(viewGroup.getChildAt(i));
}
}
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
inject(this);
}
...
To disable contextual selection menu:
#Override
public ActionMode startActionMode(ActionMode.Callback callback) {
return new ActionMode() {
#Override
public void setTitle(CharSequence charSequence) {
}
#Override
public void setTitle(int i) {
}
#Override
public void setSubtitle(CharSequence charSequence) {
}
#Override
public void setSubtitle(int i) {
}
#Override
public void setCustomView(View view) {
}
#Override
public void invalidate() {
}
#Override
public void finish() {
}
#Override
public Menu getMenu() {
return null;
}
#Override
public CharSequence getTitle() {
return null;
}
#Override
public CharSequence getSubtitle() {
return null;
}
#Override
public View getCustomView() {
return null;
}
#Override
public MenuInflater getMenuInflater() {
return null;
}
};
}
It is an old post but I haven't been able to find another solution.
A simple workaround to disable context options in crosswalk view..
Go to your crosswalk project into res/menu/select_action_menu.xml
Delete or comment on the item you don't want to show
Save, build and run
This CSS should prevent context menus in both Android and IOS, as given in the cordova template
* {
-webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
}
body {
-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
-webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
-webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
}
I have created a cellList :
I want to add a clickhandler when user clicks on button "Send"
Please Help. FieldUpdater should work if user clicks on "Send" button.
Here is the code :
final String imageHtml =AbstractImagePrototype.create(images.contact()).getHTML();
// first make a list of HasCell type - MyClass is the type of object being displayed in the CellList (could be String for simple labels)
List<HasCell<contactinfo, ?>> hasCells = new ArrayList<HasCell<contactinfo, ?>>();
hasCells.add(new HasCell<contactinfo, String>()
{
public ButtonCell cell = new ButtonCell();
public Cell<String> getCell()
{
return cell;
}
#Override
public String getValue(contactinfo object)
{
return "Send";
}
#Override
public FieldUpdater<contactinfo, String> getFieldUpdater() {
FieldUpdater< contactinfo, String > updater= new FieldUpdater<contactinfo, String>() {
#Override
public void update(int index, contactinfo object, String value) {
Window.alert("You clicked "+object.getName());
}
};
return updater;
}
}
);
// now construct the actual composite cell using the list (hasCells)
Cell<contactinfo> myClassCell = new CompositeCell<contactinfo>(hasCells)
{
#Override
public void render(Context context, contactinfo value, SafeHtmlBuilder sb)
{
sb.appendHtmlConstant("<table><tbody><tr>");
super.render(context, value, sb);
sb.appendHtmlConstant("</tr></tbody></table>");
}
#Override
protected Element getContainerElement(Element parent)
{
// Return the first TR element in the table.
return parent.getFirstChildElement().getFirstChildElement();
}
#Override
protected <X> void render(Context context, contactinfo contactinfo, SafeHtmlBuilder sb, HasCell<contactinfo, X> hasCell)
{
this renders each of the cells inside the composite cell in a new table cell
// Value can be null, so do a null check..
if (contactinfo == null) {
return;
}
sb.appendHtmlConstant("<table>");
// Add the contact image.
sb.appendHtmlConstant("<tr><td rowspan='3'>");
sb.appendHtmlConstant(imageHtml);
sb.appendHtmlConstant("</td>");
// Add the name and address.
sb.appendHtmlConstant("<td style='font-size:95%;'>");
if(contactinfo.getName()!=null)
sb.appendEscaped(contactinfo.getName());
sb.appendHtmlConstant("</td></tr><tr><td>");
if(contactinfo.getAddress()!=null)
sb.appendEscaped(contactinfo.getRemarks());
sb.appendHtmlConstant("</td>");
Cell<X> cell = hasCell.getCell();
sb.appendHtmlConstant("<td>");
cell.render(context, hasCell.getValue(contactinfo), sb);
sb.appendHtmlConstant("</td></tr></table>");
}
};
// then make the actual cellList, passing the composite cell
cellList =new CellList<contactinfo>(myClassCell,KEY_PROVIDER);
// Add a selection model so we m select cells.
singleselectionModel = new SingleSelectionModel<contactinfo>(
KEY_PROVIDER);
cellList.setSelectionModel(singleselectionModel);
singleselectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
#Override
public void onSelectionChange(SelectionChangeEvent event) {
}
});
Also, I do not see in code any piece that handles event. Did you read through http://www.gwtproject.org/doc/latest/DevGuideUiCustomCells.html#cell-onBrowserEvent
Have you tried the code sample provided by GWT - http://gwt.googleusercontent.com/samples/Showcase/Showcase.html#!CwCellSampler . Browse the "Source Code" !!!
If you have not read already then you should start here # DevGuideUiCustomCells
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.