I found this link that states how I could make the glow effect on my ImageButton. So whenever the user press the ImageButton the onTouchEvent() function is called and there I call the setImageBitmap() function. The problem is this function (setImageBitmap()) seems to have no effect at all.
What works:
1) So far I extended the ImageButton as below
// Pen.java
public class Pen extends ImageButton {
public Pen(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Now I am setting Pen");
return true;
}
}
Then inside Activity I create Pen (custom ImageButton) instance, define setGlow() and call setImageBitmap() from instance of Pen.
//MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Pen myImgbutton;
myImgbutton = (Pen) findViewById(R.id.pen);
myImgbutton.setImageBitmap(setGlow(R.drawable.pen));
}
}
public Bitmap setGlow(int resourceId) {
......
}
What doesn't work:
1) All same as above ( extending a ImageButton in android ), but this time I am calling the
setImageBitmap function from inside onTouchEvent(). For this case I have define setGlow function in inside Pen.java
// Pen.java
public class Pen extends ImageButton {
public Pen(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Now I am setting Pen");
// Here I say to apply the glow effect to the image
setImageBitmap(setGlow(R.drawable.pen));
return true;
}
public Bitmap setGlow(int resourceId) {
....
}
}
Then in xml file I do :
.....
<com.example.testsetimagebmp.Pen
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/pen"
android:background="#drawable/pen" />
....
Finally in MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// ....
}
I think this might be the classic out of memory issue. You can try to use the bitmap of the launcher icon if you want to check whether this is true:
public class Pen extends ImageButton {
public Pen(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Now I am setting Pen");
// Here I say to apply the glow effect to the image
setImageBitmap(setGlow(R.mipmap.ic_launcher));
return true;
}
public Bitmap setGlow(int resourceId) {
....
}
}
If this is the problem check this link.
You can't do that because you will out of memory if you put setImageBitmap(setGlow(R.drawable.pen)) in onTouchEvent.
onTouchEvent will be triggered serval times per second.And you will create serval bitmaps in memory per second.It will out of memory before you setImageBitmap successfully.
I built the project as you post, but it works fine. It sets the Bitmap correctly. So maybe the getGlow() method doesn't work well. Make some Logs as below
public Bitmap setGlow(int resourceId) {
Bitmap bm = BitmapFactory.decodeResource(getResources(),resourceId);
Log.e("tag", "Size: " + bm.getByteCount());
return bm;
}
then check whether the return is right.
Related
I am working on an android application with a DrawingView.
I would like to have a button which clears the drawing view, however I cannot figure out how to make a button that calls a method in somewhere that's not the MainActivity.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
The above text is the only code in the main activity, so I do not have access to a reference of the drawingView.
public DrawingView(Context context, AttributeSet attributeSet){
super(context, attributeSet);
AsyncTask myTask = new AsyncTask() {
#Override
protected Object doInBackground(Object... objects) {
try {
DrawingView dView = (DrawingView) objects[0];
dView.connection = new Connection((DrawingView) objects[0], (Context) objects[1],new Socket("128.199.236.107", 3333));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
Object[] myObjects = new Object[2];
myObjects[0] = this;
myObjects[1] = context;
myTask.execute(myObjects);
getRes();
setupDrawing();
This is the constructor of the class DrawingView.java
There is a method in this class called "refresh", and I am trying to call it using a button. Is there any way I can do this?
The refresh method looks like this
public void refresh(){
Canvas.drawColor(0, Mode.CLEAR);
}
The MAIN ACTIVITY refresh method (called on the button press), looks like this
public void refresh(View v){
final DrawingView DV = (DrawingView) findViewById(R.id.drawing);
DV.refresh();
}
Logcat? I think
Make your shared method static by adding the "static" keyword:
public static void myFunction()
Then use:
Another Activity.myFunction();
One simpe way to cleanup your canvas is to insert this code on the OnDraw method:
Paint p=new Paint();
p.setARGB(255,100,120,140); // your background color
Rect r =new Rect();
canvas.getClipBounds(r);
canvas.drawRect(r,p);`
but it's better to perform the allocations of r and p outside of onDraw.
When I build a View in Android dynamically I have to add it to a "parent" ViewGroup by calling
myLinearLayout.addView(myView);
I know that I can supervise the ViewGroup for any children to be added via the excellent onHierarchyChangeListener, but in my case I need the feedback in the View itself. Therefore my question is:
Is there something like a View.onAddedToParent() callback or a listener that I can build on?
To make things very clear: I want the view to handle everything on its own, I am aware of the fact that I could catch the event in the "parent" and then notify the view about things, but this is not desired here. I can only alter the view
Edit: I just found onAttachStateChangeListener and it would seem to work for most situations, but I'm wondering if this is really the correct solution. I'm thinking a View might just as well be passed on from one ViewGroup to another without being detached from the window. So I would not receive an event even though I want to. Could you please elaborate on this if you have insight?
Thanks in advance
You can create custom view and do your stuff in its onAttachedToWindow
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.d("CustomView", "onAttachedToWindow called for " + getId());
Toast.makeText(getContext(), "added", 1000).show();
}
}
If you want to ensure that your customview added to correct viewgroup which you want
#Override
protected void onAttachedToWindow() {
// TODO Auto-generated method stub
super.onAttachedToWindow();
if(((View)getParent()).getId()== R.id.relativelayout2)
{
Log.d("CustomView","onAttachedToWindow called for " + getId());
Toast.makeText(context, "added", 1000).show();
}
}
According to the Android source code, a view can't be moved to another layout unless removeView() is called first on its parent, and if you look at the code of removeView(), it calls removeViewInternal(), which in turn calls an overload of removeViewInternal(), which, on this line calls view.dispatchDetachedFromWindow(), which, based on the Android source code on this line calls onDetachedFromWindow(). Then the view gets added using addView(), which calls onAttachedToWindow() in the same way.
In my opion you want like this;
CreateViews;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
#Override
public void onChildViewRemoved(View parent, View child) {
Log.e("View","removed");
if(child instanceof CustomButton){
CustomButton button = (CustomButton)child;
button.addListener();
}
}
#Override
public void onChildViewAdded(View parent, View child) {
Log.e("View","added");
if(child instanceof CustomButton){
CustomButton button = (CustomButton)child;
button.addListener();
}
}
});
for(int i = 0; i < 10; ++i){
CustomButton view = new CustomButton(this);
view.setText("Button "+i);
layout.addView(view, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
layout.removeViewAt(layout.getChildCount()-1);
}
});
}
setContentView(layout);
}
Listener;
public interface OnAddedListener {
public void addListener();
}
CustomButton class;
public class CustomButton extends Button implements OnAddedListener{
public CustomButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public CustomButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public CustomButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
public void addListener() {
Log.e("","In button add listener");
}
}
Outline of my code is :
public class MainActivity extends Activity {
Client client;
MyImageView iv;
Bitmap b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyImageView iv = new MyImageView(this);
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.untitled);
iv=(MyImageView)findViewById(R.id.ImageView1);}
iv.setImageBitmap(bMap);
}
XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.example.zooming.MyImageView
android:id="#+id/ImageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:clickable="true"
android:scaleType="matrix" />
</LinearLayout>
MyImgaeView.java
MyImageView extends View {
public MyImageView(Context ct){
super(ct);
//some other works
gestureDetector = new GestureDetector(new MyGestureDetector());
new ConnectTask().execute("");
}
//Other code
class MyGestureDetector extends SimpleOnGestureListener {
#Override
public boolean onDoubleTap(MotionEvent event) {
iv=(MyImageView)findViewById(R.id.ImageView1);
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.sample);
iv.setImageBitmap(bMap);
return true;
}
}
class connectTask extends AsyncTask<String,Bitmap,Bitmap>
{
#Override
protected Bitmap doInBackground(String... message) {
//some code to get the bitmap
publishProgress(mybitmap);
return null;
}
#Override
public void onProgressUpdate(Bitmap... values) {
super.onProgressUpdate(values);
iv=(MyImageView)findViewById(R.id.ImageView1);
if(iv==null)
Log.i("Exception",ex.toString());
iv.setImageBitmap(values[0]);
}
}
}
iv is always returning null in ConnectTask(AsynTask) while its working fine in MyGestureDetector...why? also when i am making the ConnectTask the inner class of MainActivity then its working fine...!!
You should use findViewById() only once in the right context. Three ways you could achieve this with your code:
Change Activity to contain your GestureListener and the AsynkTask as inner classes and reference the field iv of your Activity
Keep GestureListener and AsynkTask as standalone classes and add the MyImageView as parameter to their constructor. Construct the two instances for this two classes in onCreate() after the findViewById()
Put GestureListener and AsynkTask as inner classes of MyImageView and add MyImageView as parameter to their constructor. When constructing the two instances from within MyImage just pass this.
findViewById() is context sensitive. This means it searches for a view starting at the current context. If the current context is an Activity it searches thru the corresponding XML Layout. If the context is a view, it just searching from that view downwards. In your case there's a good chance that the findViewById() is searching down the view only for the id - and cant find it. I say 'a good chance' because IMO the one in onDoubleTap() should also not work.
EDIT:
When I created my first custom view, I used the tutorial provided by the Android documentation.
It also has a nice and helpful section about the context.
Please try something like this:
MyImageView extends View {
public MyImageView(Context ct){
super(ct);
//some other works
gestureDetector = new GestureDetector(new MyGestureDetector());
//no it have to be in other place
//new ConnectTask().execute("");
}
//function which set image after task, of course you can in parameter set bitmap, string
//or whatever you want
public void setImageInThread(int id_image){
new ConnectTask().execute(id_image);
}
class connectTask extends AsyncTask<Integer,Void,Bitmap>
{
#Override
protected Bitmap doInBackground(Ingeter... message) {
//some code to get the bitmap
// publishProgress(mybitmap); do you really need this?
//here you can load/decode image
Bitmap bitmapa = BitmapFactory.decodeResource(getResources(), message[0]);
return bitmapa;
}
#Override
protected void onPostExecute(Bitmap toShow) {
if(toShow == null)
return; //is error
MyImageView.this.setImageBitmap(toShow);
}
/*#Override
public void onProgressUpdate(Bitmap... values) {
super.onProgressUpdate(values);
iv=(MyImageView)findViewById(R.id.ImageView1);
if(iv==null)
Log.i("Exception",ex.toString());
iv.setImageBitmap(values[0]);
}*/
}
}
Hi i want create simple apps.i use the one customclass which name like a Drawcanvas which purpose to draw runtime canvas.so i use the ontouchListener and OnClicklistener onthis. but those event can`t working.my code is below.
this the class where i use the Custom class name like DrawCanvas
public class CanvasExample extends Activity
{
/** Called when the activity is first created. */
RelativeLayout relMainOperationLayout;
RelativeLayout relTabHeader;
RelativeLayout relMidalLayout;
RelativeLayout relBelowLayout;
Context myContext;
DrawCanvas drawCanvas;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
myContext=CanvasExample.this;
LayoutInflater layoutInflater=(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int layoutId = myContext.getResources().getIdentifier("main","layout",getPackageName());
relMainOperationLayout = (RelativeLayout) layoutInflater.inflate(layoutId,null);
relTabHeader=(RelativeLayout) relMainOperationLayout.findViewById(R.id.relHeadLayout);
relMidalLayout=(RelativeLayout) relMainOperationLayout.findViewById(R.id.relmidalLayout);
relBelowLayout=(RelativeLayout) relMainOperationLayout.findViewById(R.id.relBelowLayout);
drawCanvas=new DrawCanvas(CanvasExample.this,myContext);
drawCanvas.setBackgroundColor(Color.YELLOW);
RelativeLayout.LayoutParams drawParams=new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,400);
drawParams.addRule(RelativeLayout.BELOW, relTabHeader.getId());
//relMidalLayout.addView(drawCanvas,drawParams);
relMainOperationLayout.addView(drawCanvas,drawParams);
setContentView(relMainOperationLayout);
}
And This is my CustomClass code which extend View. Name DrawCanvas
public class DrawCanvas extends View implements View.OnTouchListener,View.OnClickListener
{
Context drawContext;
Activity drawActivity;
public DrawCanvas(Activity activity,Context context)
{
super(activity);
this.drawActivity=activity;
this.drawContext=context;
}
#Override
public void onClick(View v)
{
System.err.println("Click Here");
Toast.makeText(drawContext, "Click ", 1000).show();
}
#Override
public boolean onTouch(View v, MotionEvent event)
{
System.err.println("Touch Here");
return true;
}
}
i am new in canvas.
You have to use setOnTouchListener and setOnClickListener (though I don't think click events will help you) to register the click and touch events for your View.
public DrawCanvas(Activity activity,Context context) {
super(activity);
this.drawActivity=activity;
this.drawContext=context;
setOnTouchListener(this);
setOnClickListener(this);
}
I made a simple extension of CheckBoxPreference so that I could have my own custom view with an image icon to the left of the title. The code is below:
public class CustomCheckBoxPreference extends CheckBoxPreference {
private Drawable icon;
public CustomCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.CustomCheckBoxPreference, 0, 0);
icon = arr.getDrawable(R.styleable.CustomCheckBoxPreference_icon);
setLayoutResource(R.layout.custom_checkbox_pref);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
ImageView prefsIcon = (ImageView) view.findViewById(R.id.prefs_icon);
prefsIcon.setImageDrawable(icon);
}
The problem is that for some reason the OnPreferenceChangeListener I set to any CustomCheckboxPreference has no effect and is not stored. I tried overriding some of the android methods for the implementation calling super and then printing a line to see what gets called. Notably callChangeListener does not get called. It is this method that leads to the callback for onPreferenceChanged. I tried throwing in a call to onPreferenceChanged inside of setChecked just to see what would happen and the OnPreferenceChangeListener is null:
getOnPreferenceChangeListener().onPreferenceChange(this, checked);
This is how I set the preferencechangelistener:
mTwitterPref.setChecked(!mTwitter.needsAuth());
mTwitterPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
System.out.println("Twitter Preference Changed!");
if ((Boolean) newValue) {
if (mTwitter.needsAuth()) {
System.out.println("We Need To Login To Twitter!");
IntentUtils.startActivityForResult(ProfileAccountsActivity.this,
TwLoginActivity.class, ACTIVITY_OAUTH);
}
} else {
showDialog(DIALOG_LOGOUT_TWITTER);
}
return false;
}
});
I am a bit confused as to why the preferencechangelistener is not working properly as I only overwrite onBindView and the constructor; I call super in both. Any thoughts?
Set android:focusable="false" and android:clickable="false" on the CheckBox:
<CheckBox
android:id="#+android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false" />
More info on this thread: Clickable rows on custom ArrayAdapter
I had the same issue with custom button. I tried the solution provided by #jeanh and it works. But my button was not pressed, only area around it was highlighted. Moreover, what if you have a few buttons? Obviously, that this solution won't work. So, I decided to dig deeper and my solution was below:
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/widget_frame" android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="5dp"
>
<!-- define my button -->
<Button android:id="#android:id/title"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="17sp"
android:typeface="sans"
android:textStyle="bold"
android:textColor="#000000"
></Button>
</RelativeLayout>
Java class:
public class ButtonPreference extends Preference {
private final String TAG = getClass().getName();
public interface ButtonListener {
public void onCustomClick();
}
public ButtonListener buttonListener;
public void setButtonListener(ButtonListener buttonListener){
this.buttonListener = buttonListener;
}
public ButtonPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected View onCreateView(ViewGroup parent){
RelativeLayout layout = null;
try {
LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (RelativeLayout)mInflater.inflate(R.layout.button_preference, parent, false);
//FIND OUR BUTTON IN LAYOUT
Button button = (Button) layout.findViewById(android.R.id.title);
if(button!=null){
Log.e(TAG, "button found");
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(buttonListener!=null){
buttonListener.onCustomClick(); //INVOKE OUR EVENT!
}
}
});
}
}
catch(Exception e)
{
Log.e(TAG, "Error creating info preference", e);
}
return layout;
}
}
HOW TO USE IT? Simple!
public class WallpaperSettings extends PreferenceActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
ButtonPreference defaultSettingsButton = (ButtonPreference) findPreference(EngineCore.pref+"defaultSettings");
defaultSettingsButton.setButtonListener(new ButtonListener() {
#Override
public void onCustomClick() {
Gdx.app.log("ButtonListener", "onCustomClick");
}
});
}
}
I hope it helps someone else.
I found solution !
In my case, I extends DialogPreference to my custom Dialog class,
public class SvDialogPreference extends DialogPreference
I also confuse, because in PreferenceFragment, onPreferenceChange never worked.
SvDialogPreference pref= (SvDialogPreference) findPreference("mainKey");
if( pref != null ) {
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// Never execute !
}}
To resolve this. I called "super.callChangeListener" in onDialogClosed.
public class SvDialogPreference extends DialogPreference{
....
#Override
protected void onDialogClosed(boolean positiveResult) {
double InputValue = Double.parseDouble(KEY.getText().toString());
super.callChangeListener(InputValue);
super.onDialogClosed(positiveResult);
}
Now, onPreferenceChange worked fine !