Can anyone help me to do this.
I am trying to build an android app but stuck in between.
i have use the following code to move a image.
iv is ImageView object
moveImage = new TranslateAnimation( 0, xDest, 0, -yDest);
moveImage.setDuration(1000);
moveImage.setFillAfter( true );
iv.startAnimation(moveImage);
code:
public class gameLogic extends Activity
{
ImageView image;
TranslateAnimation moveImage;
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.game_logic);
imageMoveRandom(imageList(image,0));
}
ImageView imageList(ImageView v,int i)
{
v = (ImageView) findViewById(R.id.rabbit);
int imgId;
int j = i;
TypedArray imgs = getResources().obtainTypedArray(R.array.random_imgs);
//get resourceid by index
imgId = imgs.getResourceId(j, 0);
// or set you ImageView's resource to the id
v.setBackgroundResource(imgId);
return v;
}
void imageMoveRandom(ImageView iv)throws NotFoundException
{
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics( dm );
int xDest = dm.widthPixels/2;
int yDest = dm.heightPixels/2;
// Toast.makeText(gameLogic.this, dm.widthPixels, Toast.LENGTH_SHORT).show();
// Toast.makeText(this, dm.heightPixels, 2000).show();
moveImage = new TranslateAnimation( 0, xDest, 0, -yDest);
moveImage.setDuration(1000);
moveImage.setFillAfter( true );
iv.startAnimation(moveImage);
//moveImage.reset();
}
}
Above is not full code..but part which may be helpful for references.
But i want to continuously move the image in random place but within the android display.
Can any one suggest the solution.
Thanks in Advance :)
class BitmapView extends View
{
changingX=10;
changingY=10;
public BitmapView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.yourImageName);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp, changingX,changingY, null);
changingX=changingX+5;
changingY=changingY+10;
invalidate();
}
}
Try this
Related
I'm doing a lockscreen with gridview puzzle i have successfully trigered lockscreen on Screen of and screen on when i have only buttons in my lockscrean when i add grid view in my lockscreen the activity is not coming when i screen on.
Below is my Lockscreen Service without gridview:
public class LockscreenService extends Service {
private LinearLayout linearLayout;
private WindowManager.LayoutParams layoutParams;
private WindowManager windowManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
BroadcastReceiver screenReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF) && linearLayout == null) {
init();
}
}
};
#Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenReceiver, intentFilter);
windowManager = ((WindowManager) getSystemService(WINDOW_SERVICE));
layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION,
PixelFormat.TRANSLUCENT);
}
private void init() {
linearLayout = new LinearLayout(this);
windowManager.addView(linearLayout, layoutParams);
((LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(R.layout.lockscreen, linearLayout);
// View btnClose = linearLayout.findViewById(R.id.button);
View btnClose = linearLayout.findViewById(R.id.button8);
btnClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do something when the corky3 is clicked
windowManager.removeView(linearLayout);
linearLayout = null;
}
});
}
it gives a lock screen like this lockscreen without gridview
When i add lockscreen to the linearlayout in init() methid like this
public class LockscreenService extends Service {
String p;
ImageView myImage;
final ArrayList<Bitmap> beforeshuffle = new ArrayList<>(9);
final ArrayList<Bitmap> aftershuffle = new ArrayList<>(9);
ArrayList<Bitmap> smallimages = new ArrayList<Bitmap>(9);
GridView grid;
Bitmap bs;
Bitmap as;
private LinearLayout linearLayout;
private WindowManager.LayoutParams layoutParams;
private WindowManager windowManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
BroadcastReceiver screenReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF) && intent.getAction().equals(Intent.ACTION_SCREEN_ON)&& linearLayout == null) {
init();
}
}
};
#Override
public void onCreate() {
Log.d("jhg","inservice");
super.onCreate();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenReceiver, intentFilter);
windowManager = ((WindowManager) getSystemService(WINDOW_SERVICE));
layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION,
PixelFormat.TRANSLUCENT);
}
private void init() {
// Log.d("hdkjfh","in init");
linearLayout = new LinearLayout(this);
windowManager.addView(linearLayout, layoutParams);
((LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(R.layout.lockscreen, linearLayout);
// View btnClose = linearLayout.findViewById(R.id.button);
// grid = (GridView) linearLayout.findViewById(R.id.gridView);
// grid = (GridView) findViewById(R.id.gridView);
Globalvariable c = new Globalvariable();
String p = c.givedata();
Log.d("fg", p);
bs = c.giveBitmap();
// Bitmap bitmap = (Bitmap) i.getParcelableExtra("bitmap");
//smallimage_Numbers is to tell how many smallimage_s the image should split
int smallimage_Numbers = 9;
//Getting the source image to split
// ImageView image = (ImageView) findViewById(R.id.source_image);
// File imgFile = new File("profile.jpg"
Bitmap myBitmap = BitmapFactory.decodeFile(p);
//Drawable d = new BitmapDrawable(getResources(), myBitmap);
// myImage= (ImageView) linearLayout.findViewById(R.id.My);
// myImage = (ImageView) findViewById(R.id.My);
// myImage.setImageBitmap(myBitmap);
// myImage.setVisibility(View.INVISIBLE);
splitImage(myBitmap, smallimage_Numbers);
View btnClose = linearLayout.findViewById(R.id.button8);
btnClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do something when the corky3 is clicked
Bitmap as = getBitmapFromView(grid);
if (bs.sameAs(as)) {
Toast.makeText(getApplicationContext(), "CORRECT", Toast.LENGTH_SHORT).show();
windowManager.removeView(linearLayout);
linearLayout = null;
} else {
Toast.makeText(getApplicationContext(), "WRONG", Toast.LENGTH_SHORT).show();
}
}
});
}
//invoking this method makes the actual splitting of the source image to given number of smallimage_s
//Image.setImageBitmap(decodeSampledBitmapFromFile(file.getAbsolutePath(), 500, 250));
/**
* Splits the source image and show them all into a grid in a new activity
*
* #param
* #param smallimage_Numbers The target number of small image smallimage_s to be formed from the source image
*/
public void splitImage(Bitmap bit, int smallimage_Numbers) {
//For the number of rows and columns of the grid to be displayed
int rows, cols;
//For height and width of the small image smallimage_s
int smallimage_Height, smallimage_Width;
//To store all the small image smallimage_s in bitmap format in this list
smallimages = new ArrayList<Bitmap>(smallimage_Numbers);
//Getting the scaled bitmap of the source image
// BitmapDrawable mydrawable = (BitmapDrawable) image.getDrawable();
Bitmap bitmap = bit;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);
rows = cols = (int) Math.sqrt(smallimage_Numbers);
smallimage_Height = bitmap.getHeight() / rows;
smallimage_Width = bitmap.getWidth() / cols;
//xCo and yCo are the pixel positions of the image smallimage_s
int yCo = 0;
for (int x = 0; x < rows; x++) {
int xCo = 0;
for (int y = 0; y < cols; y++) {
smallimages.add(Bitmap.createBitmap(scaledBitmap, xCo, yCo, smallimage_Width, smallimage_Height));
xCo += smallimage_Width;
}
yCo += smallimage_Height;
}
Array[] in = new Array[9];
//Collections.shuffle(smallimages);
grid.setAdapter(new ImageAdapter(this, smallimages));
grid.setNumColumns((int) Math.sqrt(smallimages.size()));
Collections.shuffle(smallimages);
grid.setAdapter(new ImageAdapter(this, smallimages));
grid.setNumColumns((int) Math.sqrt(smallimages.size()));
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
int counter = 0;
int firstclick;
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
counter++;
if (counter % 2 == 0) {
firstclick = position;
Bitmap data1 = smallimages.get(position);
} else {
Bitmap swapImage = smallimages.get(position);
smallimages.set(position, smallimages.get(firstclick));
smallimages.set(firstclick, swapImage);
grid.invalidateViews();
}
for (int i = 0; i < smallimages.size(); i++) {
aftershuffle.add(smallimages.get(i));
}
}
});
//activity to show these smallimage_s into a grid
}
//to compare two bitmaps in gridview
{
#Override
public void onClick (View v){
Bitmap as = getBitmapFromView(grid);
if (bs.sameAs(as)) {
Toast.makeText(getApplicationContext(), "CORRECT", Toast.LENGTH_SHORT).show();
windowManager.removeView(linearLayout);
linearLayout = null;
} else {
Toast.makeText(getApplicationContext(), "WRONG", Toast.LENGTH_SHORT).show();
}
}
});
*/
public static Bitmap getBitmapFromView(View view){
Bitmap bitmap =Bitmap.createBitmap(view.getWidth(),view.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas =new Canvas(bitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable!=null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return bitmap;
}
}
it returns nothing when i click screen on and off. Help me to show my shuffled grid view in my lockscreen.
I don't find the place where you make reference to the GridView "grid". Are those two lines intended to be commented? Also can you provide the implementation of your ImageAdapter?
I am new to Android and I am trying to Build a gallery app with Edit Activity. I have attached the screenshot of edit screen of my app. There is an ImageView, a SeekBar and 4 ImageButtons. The ImageButtons implements 4 edit functionality-Brightness,saturation and etc.. I have all methods for effects. All I want to know is when I click the imageButton(may be brightness), and drag the seekbar, the brightness should increase and similarly, when i click Contrast ImageButton and drag the seekbar, Contrast of Image should Increase. How can I implement it. Could Someone Please help me with it.. I tried using setOnTouchListener() for ImageButtons but that dint work, as it accepts only view as parameter and not Bitmap. Please help me.Thanks in Advance
Below is my Edit Activity
public class EditActivity extends Activity
{
private Bitmap bitmap;
private ImageView image;
private ImageButton bb,sab,shb,cb;
private BitmapDrawable drawable;
private SeekBar seekBar;
#Override
public void onCreate( Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.filters);
// Get intent data
Intent i = getIntent();
// Selected image id
final int position = i.getExtras().getInt("id");
ImageAdapter imageAdapter = new ImageAdapter(this);
image = (ImageView) findViewById(R.id.imageView);
image.setImageResource(imageAdapter.ids[position]);
bb = (ImageButton) findViewById(R.id.brightButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
bb.setImageBitmap(bitmap);
sab=(ImageButton)findViewById(R.id.saturationButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
sab.setImageBitmap(bitmap);
cb=(ImageButton) findViewById(R.id.contrastButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
cb.setImageBitmap(bitmap);
shb=(ImageButton) findViewById(R.id.sharpButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
shb.setImageBitmap(bitmap);
SeekBar seekBar=(SeekBar)findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
{
int brightness;
#Override
public void onStopTrackingTouch(SeekBar arg0) {
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
}
#Override
public void onProgressChanged(SeekBar arg0, final int progress, boolean arg2)
{
brightness = progress;
Bitmap bBitMap = brightClicked(bitmap,progress);
image.setImageBitmap(bBitMap);
Bitmap saBitMap = sharpClicked(bitmap,progress);
image.setImageBitmap(saBitMap);
Bitmap cBitMap = saturationClicked(bitmap,progress);
image.setImageBitmap(cBitMap);
Bitmap shBitMap = contrastClicked(bitmap,progress);
image.setImageBitmap(shBitMap);
}
});
}
public Bitmap brightClicked(Bitmap bbitmap,int value)
{
Bitmap bmOut= Bitmap.createBitmap(bbitmap.getWidth(), bbitmap.getHeight(),bbitmap.getConfig());
int A, R, G, B;
int pixel;
for(int i=0; i<bbitmap.getWidth(); i++){
for(int j=0; j<bbitmap.getHeight(); j++)
{
pixel = bbitmap.getPixel(i, j);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
R += value;
if (R > 255)
{
R = 255;
} else if (R < 0)
{
R = 0;
}
G += value;
if (G > 255)
{
G = 255;
} else if (G < 0)
{
G = 0;
}
B += value;
if (B > 255)
{
B = 255;
} else if (B < 0)
{
B = 0;
}
bmOut.setPixel(i, j, Color.argb(A, R, G, B));
}
}
return bmOut;
}// and other methods of effects like sharpness,contrast..
Below is Screenshot of EditImage
I would begin with defining state so that the SeekBar can quickly determine which attribute it should be modifying (contrast, brightness, sharpness, saturation). Throw these into an enum class (Google recommends avoiding enums in Android) if you like or define them within the class itself as ints. For example:
public class EditActivity extends Activity {
private int currentState;
private static final int SATURATE = 0;
private static final int CONTRAST = 1;
....
}
Now you can just have the state be updated based on the button clicked:
bb = (ImageButton) findViewById(R.id.brightButton);
bb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
currentState = BRIGHTNESS;
}
}
Then use a switch-case statement to quickly determine the state of the Activity and adjust the image accordingly through your image methods.
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
{
#Override
public void onProgressChanged(SeekBar arg0, final int progress, boolean arg2)
{
brightness = progress;
switch (currentState) {
case (SATURATE) :
image.setImageBitmap(saturationClicked(bitmap,progress));
break;
case (CONTRAST) :
image.setImageBitmap(contrastClicked(bitmap,progress));
break;
It looks like your current implementation would run all your filters on the image any time the seek bar is moved, which I imagine would cause horrible performance. A switch case would just help you avoid that.
I am a programmer with a Windows background and I am new to Java and Android stuff.
I want to create a widget (not an app) which displays a chart. After a long research I know I can do this with Canvas, imageviews and Bitmaps. The canvas which I paint on should be the same as the Widget Size.
How do I know the widget size (or imageview size) so that I can supply it to the function?
Bitmap.createBitmap(width_xx, height_yy, Config.ARGB_8888);
Code Snippet:
In the timer run method:
#Override
public void run() {
Bitmap bitmap = Bitmap.createBitmap(??, ??, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// Create a new paint
Paint p = new Paint();
p.setAntiAlias(true);
p.setStrokeWidth(1);
// Draw circle
// Here I can use the width and height to scale the circle
canvas.drawCircle(50, 50, 7, p);
remoteViews.setImageViewBitmap(R.id.imageView, bitmap);
From what I've learnt, you can only calculate widget dimensions on Android 4.1+.
When on a lower API, you'll have to use static dimensions.
About widget dimensions: App Widget Design Guidelines
int w = DEFAULT_WIDTH, h = DEFAULT_HEIGHT;
if ( Build.VERSION.SDK_INT >= 16 ) {
Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);
int maxW = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
int maxH = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
int minW = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
int minH = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
if ( context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ) {
w = maxW;
h = minH;
} else {
w = minW;
h = maxH;
}
}
Have a look at the method:
public void onAppWidgetOptionsChanged (Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)
It will be called each time you start/resize the widget.
Getting the widget width/height can be done as follows:
newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
I am currently using this:
private void run() {
int width = 400, height = 400;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
Paint p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(1);
p.setAntiAlias(true);
c.drawCircle(width/2, height/2, radius, p);
remoteViews.setImageViewBitmap(R.id.imageView, bitmap);
ComponentName clockWidget = new ComponentName(context,
Clock_22_analog.class);
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
appWidgetManager.updateAppWidget(clockWidget, remoteViews);
}
You can use this
Bitmap image1, image2;
Bitmap bitmap = Bitmap.createBitmap(image1.getWidth(), image1.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
You can create a custom widget and set the size of wight on its onMeasure() method. And also save the size at that time so that you can use it further for image creation...
I've not worked on Widgets, but I have some experience getting ImageView's size.
Here is some code I use:
public class ViewSizes {
public int width;
public int height;
public boolean isEmpty() {
boolean result = false;
if (0 >= width || 0 >= height) {
result = true;
}
return result;
}
}
That's just a dummy class containing the size parameters.
public static ViewSizes getSizes(View view) {
ViewSizes sizes = new ViewSizes();
sizes.width = view.getWidth();
sizes.height = view.getHeight();
if (sizes.isEmpty()) {
LayoutParams params = view.getLayoutParams();
if (null != params) {
int widthSpec = View.MeasureSpec.makeMeasureSpec(params.width, View.MeasureSpec.AT_MOST);
int heightSpec = View.MeasureSpec.makeMeasureSpec(params.height, View.MeasureSpec.AT_MOST);
view.measure(widthSpec, heightSpec);
}
sizes.width = view.getMeasuredWidth();
sizes.height = view.getMeasuredHeight();
}
return sizes;
}
This method calculates the width forcing a measure cycle if such has not already happened.
public static boolean loadPhoto(ImageView view, String url, float aspectRatio) {
boolean processed = false;
ViewSizes sizes = ViewsUtils.getSizes(view);
if (!sizes.isEmpty()) {
int width = sizes.width - 2;
int height = sizes.height - 2;
if (ASPECT_RATIO_UNDEFINED != aspectRatio) {
if (height * aspectRatio > width) {
height = (int) (width / aspectRatio);
} else if (height * aspectRatio < width) {
width = (int) (height * aspectRatio);
}
}
// Do you bitmap processing here
processed = true;
}
return processed;
}
This one is probably useless for you. I give just as an example - I have an ImageView and image URL, which should be parametrized with image and height.
public class PhotoLayoutListener implements OnGlobalLayoutListener {
private ImageView view;
private String url;
private float aspectRatio;
public PhotoLayoutListener(ImageView view, String url, float aspectRatio) {
this.view = view;
this.url = url;
this.aspectRatio = aspectRatio;
}
boolean handled = false;
#Override
public void onGlobalLayout() {
if (!handled) {
PhotoUtils.loadPhoto(view, url, aspectRatio);
handled = true;
}
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
removeLayoutListenerPre16(viewTreeObserver, this);
} else {
removeLayoutListenerPost16(viewTreeObserver, this);
}
}
}
#SuppressWarnings("deprecation")
private void removeLayoutListenerPre16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
observer.removeGlobalOnLayoutListener(listener);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void removeLayoutListenerPost16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
observer.removeOnGlobalLayoutListener(listener);
}
}
This is just a layout listener - I want to process the image loading once the layout phase has finished.
public static void setImage(ImageView view, String url, boolean forceLayoutLoading, float aspectRatio) {
if (null != view && null != url) {
final ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (forceLayoutLoading || !PhotoUtils.loadPhoto(view, url, aspectRatio)) {
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new PhotoLayoutListener(view, url, aspectRatio));
}
}
}
}
This is the method I actually call. I give it the view and URL. The methods takes care of loading - if it can determine the view's size it starts loading immediately. Otherwise it just assigns a layout listener and start the loading process once the layout is finished.
You could strip away some parameters - forceLoading / aspectRatio should be irrelevant for you. After that change the PhotoUtils.loadPhoto method in order to create the bitmap with the width / height it has calculated.
Like Julian told us, you can get them like that with a bitmap of your image:
int width = bitmap.getWidth();
int height = bitmap.getHeight();
I do not get a grip on solving the issue.
I have manually placed two images on the screen. I would like to have an onClick event handling for each of it.
By the following approach, the OnClick Handler seems to be valid only for the background.
Acually, all created sub-views/Imagers and their onClickListeners are reacting on the parent where they have drawn onto.
The AndroidManifext.xml is only the RelativeLayout with no child tags.
public class Main extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Imager theUpperImage = new Imager( R.drawable.img1, -25, -100, new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText( v.getContext(), "Upper", Toast.LENGTH_SHORT).show();
}
});
addContentView( theUpperImage, new View.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
final Imager theLowerImage = new Imager( R.drawable.img2, -25, +50, new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText( v.getContext(), "Lower", Toast.LENGTH_SHORT).show();
}
});
addContentView( theLowerImage, new View.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
class Imager extends View {
final int resImage;
final int centerOffsetX, centerOffsetY;
public Imager(int inResImage, int inCenterOffsetX, int inCenterOffsetY, View.OnClickListener inOnClickListener) {
super( Main.this );
resImage = inResImage;
centerOffsetX = inCenterOffsetX;
centerOffsetY = inCenterOffsetY;
super.setOnClickListener( inOnClickListener );
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resImage);
final int x = (canvas.getWidth()/2)+centerOffsetX;
final int y = (canvas.getWidth()/2)+centerOffsetY;
canvas.drawBitmap(bitmap, x, y, null);
}
#Override
public void draw(Canvas canvas) {
super.draw( canvas );
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resImage);
final int x = (canvas.getWidth()/2)+centerOffsetX;
final int y = (canvas.getWidth()/2)+centerOffsetY;
canvas.drawBitmap(bitmap, x, y, null);
}
}
}
How to created freely placed images and provide them with an OnClick-functionality?
I would not stick to the above solution. Important for me is to freely place the images on the screen and have them clickable. The predefined Layouts semm not to give me a certain Layout which have a FreeLayout-functionality. (Or is the intention of Layout misleading me?)
I also keep in mind that I probably want to dynamicly remove an Image later, but I am not there yet.
Thank you a lot for help in advance,
Dirk
I'm new with Android.
In my project I have the custom View MyView with the follow code
public class MyView extends View {
private final Bitmap baseBitmap = BitmapFactory.decodeResource(
getResources(), R.drawable.myImage);
private final Matrix matrix;
private boolean active = true;
public MyView(Context context, Matrix matrix) {
super(context);
this.matrix = matrix;
this.setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (active) {
System.out.println("draw "+this.getId());
canvas.drawBitmap(baseBitmap, matrix, null);
} else {
...
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
System.out.println("--------->"+this.getId());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
this.matrix.setTranslate(event.getX()-(baseBitmap.getWidth()/2), event.getY()-(baseBitmap.getHeight()/2));
this.invalidate();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
this.active = false;
}
return true;
}
In my Activity, I instantiate MyView many times and then add them to the main layout. This is its code:
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Display display = getWindowManager().getDefaultDisplay();
float cx = display.getWidth() / 2, cy = display.getHeight() / 2;
int radius = 80;
double distance = 0, distancePoint = 0;
final int flags = PathMeasure.POSITION_MATRIX_FLAG
| PathMeasure.TANGENT_MATRIX_FLAG;
float length = 0;
setContentView(R.layout.main);
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main_view);
Path pathCircle = new Path();
pathCircle.addCircle(cx, cy, radius, Direction.CW);
PathMeasure meas = new PathMeasure(pathCircle, false);
int nObject = 10;
length = meas.getLength();
distance = length/nObject;
int i = 0;
while(i<nObject){
Matrix m = new Matrix();
meas.getMatrix((float)distancePoint, m, flags);
MyView myView = new MyView(this, m);
System.out.println(myView.toString());
myView.setId(i);
mainLayout.addView(myView,i);
i++;
distancePoint = distance*i;
}
}
}
At runtime, when I touch any MyView element I always get the last. With "System.out.println("--------->"+this.getId());" I can see that the id of the touched element is always the last, even if I toch the first or any other element. Actualy, I just can move the last element.
Does anyone know why can't I get the event of the right istance of MyView touched?
(I hope my question is clear)
Thanks
I changed the code adding the onMeasure method. I used the code of a tutorial, dimensions are not specific for my image. The views are drawn and the result is the same, unfortunately with the same problem. I post the layout xml too, maybe could be useful.
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Display display = getWindowManager().getDefaultDisplay();
float cx = display.getWidth() / 2, cy = display.getHeight() / 2;
int radius = 80;
double distance = 0, distancePoint = 0;
final int flags = PathMeasure.POSITION_MATRIX_FLAG
| PathMeasure.TANGENT_MATRIX_FLAG;
float length = 0;
setContentView(R.layout.main);
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main_view);
Path pathCircle = new Path();
pathCircle.addCircle(cx, cy, radius, Direction.CW);
PathMeasure meas = new PathMeasure(pathCircle, false);
int nObject = 10;
length = meas.getLength();
distance = length/nObject;
int i = 0;
while(i<nObject){
Matrix m = new Matrix();
meas.getMatrix((float)distancePoint, m, flags);
MyView myView = new MyView(this, m);
System.out.println(myView.toString());
myView.setId(i);
nt spec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
myView.measure(spec, spec);
mainLayout.addView(myView,i);
i++;
distancePoint = distance*i;
}
}
}
public class MyView extends View {
private final Bitmap baseBitmap = BitmapFactory.decodeResource(
getResources(), R.drawable.myImage);
private final Matrix matrix;
private boolean active = true;
public MyView(Context context, Matrix matrix) {
super(context);
this.matrix = matrix;
this.setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (active) {
System.out.println("draw "+this.getId());
canvas.drawBitmap(baseBitmap, matrix, null);
} else {
...
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
System.out.println("--------->"+this.getId());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
this.matrix.setTranslate(event.getX()-(baseBitmap.getWidth()/2), event.getY()-(baseBitmap.getHeight()/2));
this.invalidate();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
this.active = false;
}
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int chosenWidth = chooseDimension(widthMode, widthSize);
int chosenHeight = chooseDimension(heightMode, heightSize);
int chosenDimension = Math.min(chosenWidth, chosenHeight);
setMeasuredDimension(chosenDimension, chosenDimension);
}
private int chooseDimension(int mode, int size) {
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
return size;
} else { // (mode == MeasureSpec.UNSPECIFIED)
return getPreferredSize();
}
}
// in case there is no size specified
private int getPreferredSize() {
return 300;
}
}
The main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/main_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FF66FF33">
</RelativeLayout>
I'm pretty sure that it's because you're basically piling up your views at the top left corner of your RelativeLayout. So, only the uppermost (the last one added) is touchable.
I think that if you try adding them to a LinearLayout, as a test, you'll see that your view works. Setting LayoutParams for a RelativeLayout programmatically is not very comfy IMHO.
EDIT
I tried your code. The fact is that your views are just made to be drawn one over the other, or else the overall drawing wouldn't come, so my first guess is right (the uppermost covers the others - even in its transparent parts)(btw try Hierarchy Viewer and you can see that yourself). So you need to do your job in a single view, or handle the touches like this:
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if(!isPetaloTouched()) {// check if the actual drawing was touched
return false; // discard the event so that it reaches
// the underlying view
}
//......
See this post for an explanation of how events work in Android.
Both ways would need an isPetaloTouched() logic to detect if/which drawing must be moved, but the first would be more efficient of course.
Also, forget about the onMeasure() thing, I thought that could help giving the view a size around which to wrap, so that it wouldn't fill its parent and aligning views aside would make sense. However, be sure that the touch would work if the views were not piled up.
(...allora mPetali stava proprio per petali!)