Put generated ImageView in xml ImageView - android

I have a layout activity_main that (among other things) shows ImageView:
<ImageView
android:id="#+id/profileImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView2"
android:layout_alignLeft="#+id/login_button" />
I've created a class that extendsImageView and shows animated gif:
public class AnimatedGif extends ImageView
{
private Movie mMovie;
private long mMovieStart = 0;
public AnimatedGif(Context context, InputStream stream)
{
super(context);
mMovie = Movie.decodeStream(stream);
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawColor(Color.TRANSPARENT);
super.onDraw(canvas);
final long now = SystemClock.uptimeMillis();
if (mMovieStart == 0)
{
mMovieStart = now;
}
final int realTime = (int)((now - mMovieStart) % mMovie.duration());
mMovie.setTime(realTime);
mMovie.draw(canvas, 10, 10);
this.invalidate();
}
}
In the main activity I use the following code:
setContentView(R.layout.activity_main);
.
.
.
InputStream stream = this.getResources().openRawResource(R.drawable.searching_gif);
AnimatedGif gifImageView = new AnimatedGif(this, stream);
ImageView im = (ImageView)findViewById(R.id.profileImageView);
How can I make that im will show gifImageView??

you can't. At least the way you though about it. You need some minimal changes, to load your AnimatedGif directly into the layout. The first is a constructor that takes as parameter the Context and the AttributeSet:
public AnimatedGif(Context context, AttributeSet attrs) {
}
this way you can add it directly as item of the xml, specifying the full qualified package to the class
<com.package.AnimatedGif
android:id="#+id/profileImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView2"
android:layout_alignLeft="#+id/login_button" />
now you probably want to have a custom attribute to specify the gif you want to load. So you could declare in your attr.xml file
<declare-styleable name="AnimatedGif">
<attr name="gifres" format="integer" />
</declare-styleable>
and inside the constructor you can load it like
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AnimatedGif);
int value = a.getInt(R.styleable.AnimatedGif_gifres, 0));
stream = context.getResources().openRawResource(value);
a.recycle();

How can I make that im will show gifImageView??
Because activity_main.xml is layout for Activity in which want to add custom ImageView using code:
1. Use LinearLayout in activity_main.xml as root Layout and set orientation to vertical
2. Assign id to root Layout of activity_main.xml like:
android:id="#+id/main_layout"
3. Get root layout in onCreate method:
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.main_layout);
4. Now add gifImageView view object to linearLayout:
linearLayout.addView(gifImageView);

Related

Android: Relative Layout/Bitmap Alpha overwriting

I try to display a bitmap with a specific alpha. The Bitmap is created in ARGB format, for each pixel I set the color with value 0x04FFAAAA.
The display is made in a class that extends GLSurfaceView (the class name is BitmapView).
I have another class RelativeLayoutBitmap (extends RelativeLayout), that creates and addView BitmapView.
In screen.xml
I define a relative layout :
<RelativeLayout
android:id="id"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/overlay_background">
<RelativeLayoutBitmap
android:id="id_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</RelativeLayout>
public RelativeLayoutBitmap(Context context, AttributeSet attrs) {
super(context, attrs);
internalConstruct(context, attrs);
}
public RelativeLayoutBitmap(Context context) {
super(context);
internalConstruct(context, null);
}
private void internalConstruct(Context context, AttributeSet attrs){
this.mContext = context;
this.mAttrs = attrs;
if (null != mBitmapView) {
this.removeView(mBitmapView);
mBitmapView = null;
}
// create the bitmapview
mBitmapView = new BitmapView(mContext, mAttrs);
mBitmapView(getBackground()); //same background for mBitmapView
LayoutParams params = (LayoutParams) this.generateDefaultLayoutParams();
params.width = LayoutParams.MATCH_PARENT;
params.height = LayoutParams.MATCH_PARENT;
mBitmapView.setLayoutParams(params);
this.addView(mBitmapView, 0);
}
Over this relativeLayout, I have a relativeLayout with a background 0x4D000000.
This doesn't work, the Bitmap was displayed, but visible; I hoped the bitmap will be display and not visibile because the alpha of each pixel was 0.015f.
If I hide the relativeLayout over (or set background to be transparent), the bitmap was displayed and not visibile (if I change the alpha of each pixel to 1.0 the Bitmap is visible.).
If in my screen.xml, I include the BitmapView:
<RelativeLayout
android:id="id"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/overlay_background">
<BitmapView
android:id="id_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</RelativeLayout>
This works, the Bitmap was displayed and not visible; then if I change the alpha of each pixel to 1.0 the Bitmap is visible.
For my final project, I can't modify the app, the BitmpaView must be included in RelativeLayoutBitmap.
I don't understand why I don't have the comportment I expect when my BitmapView is added in a RelativeLayout.
In RelativeLayoutBitmap, what do I need to set to have the bitmap displayed with the alpha of each pixel?

Need the image id from xml attributes custom widget

I have a custom control (very simple for now) that is like a button. It needs to display an unpressed and a pressed image. It appears multiple times in the activity and has different pairs of images depending on where it's used. Think of toolbar icons - similar to that.
Here's an extract of my layout:
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:MyApp="http://schemas.android.com/apk/res/com.example.mockup"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TableRow>
<com.example.mockup.ImageGestureButton
android:id="#+id/parent_arrow"
android:src="#drawable/parent_arrow"
MyApp:srcPressed="#drawable/parent_arrow_pressed"
... />
...
</TableRow>
</TableLayout>
attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ImageGestureButton">
<attr name="srcPressed" format="reference" />
</declare-styleable>
</resources>
And, in the R.java, one finds:
public static final class drawable {
public static final int parent_arrow=0x7f020003;
public static final int parent_arrow_pressed=0x7f020004;
...
}
During widget instantiation, I want to determine the ids declared in the activity xml. How do I do that? I've tried this (I updated my original post with working code; so, the following works.)
public class ImageGestureButton extends ImageView
implements View.OnTouchListener
{
private Drawable unpressedImage;
private Drawable pressedImage;
public ImageGestureButton (Context context, AttributeSet attrs)
{
super(context, attrs);
setOnTouchListener (this);
unpressedImage = getDrawable();
TypedArray a = context.obtainStyledAttributes (attrs, R.styleable.ImageGestureButton, 0, 0);
pressedImage = a.getDrawable (R.styleable.ImageGestureButton_srcPressed);
}
public boolean onTouch (View v, MotionEvent e)
{
if (e.getAction() == MotionEvent.ACTION_DOWN)
{
setImageDrawable (pressedImage);
}
else if (e.getAction() == MotionEvent.ACTION_UP)
{
setImageDrawable (unpressedImage);
}
return false;
}
}
If you want to get the drawable use TypedArray.getDrawable(). In your example you are using getString().
In your declare-styleable use
<attr name="srcPressed" format="reference" />
If you want the actual resource ID for the Drawable, rather than the fully resolved Drawable it's self, you can do this:
TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.FooLayout );
TypedValue value = new TypedValue();
a.getValue( R.styleable.FooLayout_some_attr, value );
Log.d( "DEBUG", "This is the actual resource ID: " + value.resourceId );

Mimic the Overflow Spinner in a ListView Row

I'm trying to put in a Spinner on each row of a ListView within a ListFragment.
I want it to look like a vertical overflow image like in the store but I'm not able to figure out how to show the vertical overflow image that is clickable to show the options.
It always looks like below instead. I would like to remove "Options" and have the overflow image instead.
Any help is appreciated.
Found relevant ideas from other posts and combined them, thank you Stack Overflow.
Android: How to set spinner selector to own image/icon?
Declaring a custom android UI element using XML
How to get width and height of the image?
The idea is that you create a 0dp width Spinner with an ImageView over it. When you click the image, it shows the drop down. I haven't tested it's behavior when the Spinner is at the edge of the screen yet and may very well cause trouble. I also need to tweak the position of the Spinner, but this works for now.
My plan is to catch the selection from the Spinner and then open a dialog / intent based on what was clicked. Here is what it looks like. (the ImageView is faint but it's mostly a placehodler for me right now)
Before click
After click
Here is the general code I used since this seems desirable to others.
values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="OverflowSpinner">
<attr name="imageResource" format="string" />
<attr name="spinnerTextResource" format="string" />
</declare-styleable>
</resources>
values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="spinner_array">
<item>Skip</item>
<item>View log</item>
</string-array>
</resources>
layouts/row.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:awesome="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- stuff -->
<com.blah.package.OverflowSpinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
awesome:imageResource="#drawable/ic_menu_moreoverflow_normal_holo_light"
awesome:spinnerTextResource="#array/spinner_array"
/>
</RelativeLayout>
OverflowSpinner.java
public class OverflowSpinner extends RelativeLayout {
int mImage;
int mStrings;
public OverflowSpinner(Context context) {
super(context);
}
public OverflowSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
setupDisplay(context);
}
public OverflowSpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
setupDisplay(context);
}
private void init(AttributeSet attrs) {
TypedArray attribs = getContext().obtainStyledAttributes(attrs, R.styleable.OverflowSpinner);
// get attributes
mImage = attribs.getResourceId(R.styleable.OverflowSpinner_imageResource, -1);
mStrings = attribs.getResourceId(R.styleable.OverflowSpinner_spinnerTextResource, -1);
attribs.recycle();
}
private void setupDisplay(Context context) {
BitmapDrawable bitmap = (BitmapDrawable)this.getResources().getDrawable(mImage);
int height = bitmap.getBitmap().getHeight();
// set size of Spinner to 0 x height so it's "hidden"
// the height is used to help position the Spinner in a nicer spot
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context, mStrings, android.R.layout.simple_spinner_item);
// setup spinner
final Spinner spinner = new Spinner(context);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setLayoutParams(lp);
this.addView(spinner);
// set size of image to be normal
lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.addRule(ALIGN_PARENT_BOTTOM);
ImageButton option = new ImageButton(context);
option.setBackgroundResource(android.R.color.transparent);
option.setImageResource(mImage);
option.setLayoutParams(lp);
// when clicking the image button, trigger the spinner to show
option.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
spinner.performClick();
}
});
this.addView(option);
}
}

View class in ImageView

i have develop one application in which i want to play gif animation.
for that i have refer this
CODE
public class GIFDemo extends GraphicsActivity {
ImageView imageView1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageView1 = (ImageView) findViewById(R.id.imageView1);
}
private static class GIFView extends View{
Movie movie,movie1;
InputStream is=null,is1=null;
long moviestart;
long moviestart1;
public GIFView(Context context) {
super(context);
is=context.getResources().openRawResource(R.drawable.border_gif);
movie=Movie.decodeStream(is);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
super.onDraw(canvas);
long now=android.os.SystemClock.uptimeMillis();
if (moviestart == 0) { // first time
moviestart = now;
}
if(moviestart1==0)
{
moviestart1=now;
}
int relTime = (int)((now - moviestart) % movie.duration()) ;
// int relTime1=(int)((now - moviestart1)% movie1.duration());
movie.setTime(relTime);
// movie1.setTime(relTime1);
movie.draw(canvas,10,10);
//movie1.draw(canvas,10,100);
this.invalidate();
}
}
}
Main :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
<ImageView android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/imageView1"
android:src="#drawable/icon"></ImageView>
</LinearLayout>
so problem is i want to set class GIFView in Imageview so i have refer post like this
but not get proper example. so can you give me proper example and explanation that how can i set view in ImageView
Thanks
nik
I don't think it is meaningful to 'set the view' of an ImageView (in the way you are suggesting), and I don't think you even need an ImageView in this case. You have implemented a custom View that is able to draw a GIF without any dependency on the ImageView class - you just have to use it!
With minimal changes, assuming the GIFView works, you can just instantiate a GIFView and then add it to the main layout. Let your onCreate be as follows:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// let your LinearLayout have an id of 'container'
LinearLayout container = (LinearLayout) findViewById(R.id.container);
GIFView gifView = new GifView(this);
container.addView(gifView);
}
You can get rid of the ImageView from the layout entirely and just use your GIFView that was instantiated in code. Alternatively, you can make your GIFView a standalone (non-inner) class and add it to your XML layout by specifying the full package name, e.g.
<com.nik.view.GIFView
id="#+id/gifview"
... />
You would also need to write the view constructor GIFView(Context context, AttributeSet attrs) because that is the one that is expected when using XML.

Custom Android control with children

I'm trying to create a custom Android control that contains a LinearLayout. You can think of it as an extended LinearLayout with fancy borders, a background, an image on the left...
I could do it all in XML (works great) but since I have dozens of occurences in my app it's getting hard to maintain. I thought it would be nicer to have something like this:
/* Main.xml */
<MyFancyLayout>
<TextView /> /* what goes inside my control's linear layout */
</MyfancyLayout>
How would you approach this? I'd like to avoid re-writing the whole linear layout onMeasure / onLayout methods. This is what I have for the moment:
/* MyFancyLayout.xml */
<TableLayout>
<ImageView />
<LinearLayout id="container" /> /* where I want the real content to go */
</TableLayout>
and
/* MyFancyLayout.java */
public class MyFancyLayout extends LinearLayout
{
public MyFancyLayout(Context context) {
super(context);
View.inflate(context, R.layout.my_fancy_layout, this);
}
}
How would you go about inserting the user-specified content (the TextView in main.xml) in the right place (id=container)?
Cheers!
Romain
----- edit -------
Still no luck on this, so I changed my design to use a simpler layout and decided to live with a bit of repeated XML. Still very interested in anyone knows how to do this though!
This exact question bugged me for some time already but it's only now that I've solved it.
From a first glance, the problem lies in the fact that a declarative content (TextView in Your case) is instantiated sometime after ctor (where we're usually inflating our layouts), so it's too early have both declarative and template content at hand to push the former inside the latter.
I've found one such place where we can manipulate the both: it's a onFinishInflate() method. Here's how it goes in my case:
#Override
protected void onFinishInflate() {
int index = getChildCount();
// Collect children declared in XML.
View[] children = new View[index];
while(--index >= 0) {
children[index] = getChildAt(index);
}
// Pressumably, wipe out existing content (still holding reference to it).
this.detachAllViewsFromParent();
// Inflate new "template".
final View template = LayoutInflater.from(getContext())
.inflate(R.layout.labeled_layout, this, true);
// Obtain reference to a new container within "template".
final ViewGroup vg = (ViewGroup)template.findViewById(R.id.layout);
index = children.length;
// Push declared children into new container.
while(--index >= 0) {
vg.addView(children[index]);
}
// They suggest to call it no matter what.
super.onFinishInflate();
}
A labeled_layout.xml referenced above is not unlike something like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation ="vertical"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:layout_marginLeft ="8dip"
android:layout_marginTop ="3dip"
android:layout_marginBottom ="3dip"
android:layout_weight ="1"
android:duplicateParentState ="true">
<TextView android:id ="#+id/label"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:singleLine ="true"
android:textAppearance ="?android:attr/textAppearanceMedium"
android:fadingEdge ="horizontal"
android:duplicateParentState="true" />
<LinearLayout
android:id ="#+id/layout"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:layout_marginLeft ="8dip"
android:layout_marginTop ="3dip"
android:duplicateParentState="true" />
</LinearLayout>
Now (still omitting some details) elsewhere we might use it like this:
<com.example.widget.LabeledLayout
android:layout_width ="fill_parent"
android:layout_height ="wrap_content">
<!-- example content -->
</com.example.widget.LabeledLayout>
This approach saves me a lot of code! :)
As esteewhy explains, just swap the xml-defined contents into where you want them internally in your own layout, in onFinishInflate(). Example:
I take the contents that I specify in the xml:
<se.jog.custom.ui.Badge ... >
<ImageView ... />
<TextView ... />
</se.jog.custom.ui.Badge>
... and move them to my internal LinearLayout called contents where I want them to be:
public class Badge extends LinearLayout {
//...
private LinearLayout badge;
private LinearLayout contents;
// This way children can be added from xml.
#Override
protected void onFinishInflate() {
View[] children = detachChildren(); // gets and removes children from parent
//...
badge = (LinearLayout) layoutInflater.inflate(R.layout.badge, this);
contents = (LinearLayout) badge.findViewById(R.id.badge_contents);
for (int i = 0; i < children.length; i++)
addView(children[i]); //overridden, se below.
//...
super.onFinishInflate();
}
// This way children can be added from other code as well.
#Override
public void addView(View child) {
contents.addView(child);
}
Combined with custom XML attributes things gets very maintainable.
You can create your MyFancyLayout class by extending LinearLayout. Add the three constructors which call a method ("initialize" in this case) to set up the rest of the Views:
public MyFancyLayout(Context context) {
super(context);
initialize();
}
public MyFancyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public MyFancyLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
Within initialize, you do anything you need to to add the extra views. You can get the LayoutInflater and inflate another layout:
final LayoutInflater inflator = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflator.inflate(R.layout.somecommonlayout, this);
Or you can create Views in code and add them:
ImageView someImageView = new ImageView(getContext());
someImageView.setImageDrawable(myDrawable);
someImageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
addView(someImageView);
If you're going to use the Context a lot, you can store a reference to it in your constructors and use that rather than getContext() to save a little overhead.
just use something like this:
<org.myprogram.MyFancyLayout>
...
</org.myprogram.MyFancyLayout>
Useful link - http://www.anddev.org/creating_custom_views_-_the_togglebutton-t310.html

Categories

Resources