I have a collapsing toolbar with ImageView inside, when the image is clicked I want to enlarge it with an animation and go to another "activity" like whatsapp, telegram and a lot of other apps which allow user to click the profile photo of friends.
This will allow the user to see the image in the center of the screen and save or share the picture.
I had a look of Zooming a View http://developer.android.com/training/animation/zoom.html but it isn't enough and I have lag during the animation. (I used the same code provided)
I think your key is shared element transition. You can follow this tutorial
Give the same transition name to both of the views which are in different activities.
android:transitionName="#string/transition_string"
Add this bundle where you start the zoomed activity
Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(context, view, view.getTransitionName()).toBundle();
startActivity(intent,bundle);
And don't forget to add this line to your activity's style
<!-- Add this line -->
<item name="android:windowContentTransitions">true</item>
You may want to look at Google's documentation on zooming a view here
Basically the way they tell you to go about this is by creating an imagebutton that will display the smaller image, that when clicked will play an animation, and at the end reveal an imageview with the full sized image in it.
The layout they give as an example is this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<ImageButton
android:id="#+id/thumb_button_1"
android:layout_width="100dp"
android:layout_height="75dp"
android:layout_marginRight="1dp"
android:src="#drawable/thumb1"
android:scaleType="centerCrop"
android:contentDescription="#string/description_image_1" />
</LinearLayout>
<!-- This initially-hidden ImageView will hold the expanded/zoomed version of
the images above. Without transformations applied, it takes up the entire
screen. To achieve the "zoom" animation, this view's bounds are animated
from the bounds of the thumbnail button above, to its final laid-out
bounds.
-->
<ImageView
android:id="#+id/expanded_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:contentDescription="#string/description_zoom_touch_close" /></FrameLayout>
Then you can set up the animation like this:
public class ZoomActivity extends FragmentActivity {
// Hold a reference to the current animator,
// so that it can be canceled mid-way.
private Animator mCurrentAnimator;
// The system "short" animation time duration, in milliseconds. This
// duration is ideal for subtle animations or animations that occur
// very frequently.
private int mShortAnimationDuration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zoom);
// Hook up clicks on the thumbnail views.
final View thumb1View = findViewById(R.id.thumb_button_1);
thumb1View.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
zoomImageFromThumb(thumb1View, R.drawable.image1);
}
});
// Retrieve and cache the system's default "short" animation time.
mShortAnimationDuration = getResources().getInteger(
android.R.integer.config_shortAnimTime);
}}
There are several more steps, but at this point I'm literally copy and pasting from their documentation. You really should go read up on it. If you have any questions let me know!
Related
In my Android app, I am needing to implement a scene transition that involves a change in the elevation (z-index) of one of the elements. As you can see in the image below in the start scene on the left the blue arc is displayed beneath the image of the dog. In the final transition displayed on the right, the image of the dog is displayed underneath the blue arc. My desire is to have a changeBounds transition of the image start first and then slightly later do a changeBounds transition of the arc. At about halfway through the transition, the bottom of the image should be positioned above the arc. At this halfway point I'd like the elevation/z-index of the image to change so that the dog image is displayed underneath the blue arc.
I currently have the theme of my app configured to use the following transitionSet for this scene change.
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
android:transitionOrdering="together"
android:duration="2000">
<changeBounds
android:startDelay="0"
android:duration="1000"
android:resizeClip="false"
>
<targets>
<target android:targetId="#id/charlie"/>
</targets>
</changeBounds>
<transition class="com.motb.transitiontest.ElevationTransition">
android:startDelay="0"
android:duration="1000"
<targets>
<target android:targetId="#id/charlie"/>
<target android:targetId="#id/arc1"/>
</targets>
</transition>
<changeBounds
android:startDelay="300"
android:duration="1000"
>
<targets>
<target android:targetId="#id/arc1"/>
<target android:targetId="#id/helloText" />
</targets>
</changeBounds>
</transitionSet>
I'm attempting to have the elevation change using this custom "ElevationTransition" shown below:
public class ElevationTransition extends Transition {
public static final String TAG = "ElevationTransition" ;
public ElevationTransition(Context context, AttributeSet attributes ) {
super( context, attributes );
}
private static final String PROPNAME_TRANS_Z = "com.motb:transition:transz";
#Override
public void captureStartValues(TransitionValues transitionValues) {
float translationZ = transitionValues.view.getTranslationZ() ;
transitionValues.values.put(PROPNAME_TRANS_Z + "_start" , translationZ );
}
#Override
public void captureEndValues(TransitionValues transitionValues) {
float translationZ = transitionValues.view.getTranslationZ() ;
transitionValues.values.put(PROPNAME_TRANS_Z + "_end", translationZ );
}
#Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
final View view = endValues.view;
float startElevation = (Float) startValues.values.get(PROPNAME_TRANS_Z + "_start");
float endElevation = (Float) endValues.values.get(PROPNAME_TRANS_Z + "_end" );
if (startElevation != endElevation) {
view.setTranslationZ(startElevation);
return ObjectAnimator.ofFloat(view, View.TRANSLATION_Z,
startElevation, endElevation);
}
return null;
}
}
The main activity just displays the blank map using the following layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.MainActivity"
android:id="#+id/main"
android:onClick="onClick"
android:background="#drawable/treasuremap"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/fragmentContainer"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
A click on the map replaces the above FrameLayout with a fragment displaying the bottom "card" that uses the following layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="250dp"
tools:context="com.motb.transitiontest.MainActivity"
android:id="#+id/main"
android:background="#android:color/transparent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="#drawable/arc_bg"
android:backgroundTint="#ff0000ff"
android:layout_alignParentBottom="true"
android:transitionName="rv1"
android:id="#+id/arc1"
android:translationZ="20dp"
>
<TextView
android:id="#+id/helloText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World Transition Test"
android:layout_marginStart="165dp"
android:layout_marginTop="27dp"
android:textSize="40dp"
android:gravity="left"
android:transitionName="tv1"
android:textColor="#ffffffff"
/>
</RelativeLayout>
<ImageView
android:layout_width="300px"
android:layout_height="300px"
android:layout_alignParentTop="true"
android:layout_marginTop="80dp"
android:layout_marginStart="20dp"
android:transitionName="iv1"
android:src="#drawable/charlie"
android:id="#+id/charlie"
android:translationZ="30dp"
android:stateListAnimator="#null"
/>
</RelativeLayout>
A click on the fragment, starts the second activity with the larger image of the dog using the xml below:
`
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.Activity2"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.Activity2"
android:layout_marginTop="200dp"
android:background="#drawable/arc_bg"
android:layout_alignParentBottom="true"
android:transitionName="rv1"
android:id="#+id/arc1"
android:backgroundTint="#ff0000ff"
android:translationZ="40dp"
>
<TextView
android:id="#+id/helloText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:text="Hello World Transition Test"
android:textSize="40dp"
android:textAlignment="center"
android:transitionName="tv1"
android:textColor="#ffffffff"
/>
</RelativeLayout>
<ImageView
android:id="#+id/charlie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/charlie"
android:transitionName="iv1"
android:scaleType="centerCrop"
android:translationZ="0dp"
android:stateListAnimator="#null"
/>
</RelativeLayout>`
Currently, what I see is that the elevation instantly changes at the start of the transition resulting in the dog image to be obscured by the arc.
I checked the github. It's a bug.
I can categorically run the transition between scenes using Transtions and TransitionManager.go(). But, when you run the transition between the fragment and activity it always instantly changes the fade animation. There's a couple fade bugs fixed in Support 26.0.0 beta-1
When a Fade transition is interrupted and reversed, the View starts the animation from the beginning. (Fix ported from Android Framework.)
Transition.Fade ignores initial alpha of View (AOSP issue 221820)
But, ask yourself, with all your fiddling did you ever see it do an actual fade transition? -- No. Like ignore all the moving and whatever, can you get it to do a fade at all? Because that's all my suggestion needed and I can't get it running the way you have it running. But, obviously all the moving of the elements does work so it's a damned bug.
You can totally fake it too. If you had fades, you could just invoke it and get it to work. You get the correct animation if you change the onCreate() in the Activity2 to be:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
setContentView(R.layout.activity2);
findViewById(R.id.arc1).setVisibility(View.VISIBLE);
findViewById(R.id.arc2).setAlpha(0);
findViewById(R.id.arc2).animate().alpha(1).setDuration(2000).start();
}
I only set the visibility of that arc1 to the correct one because you had it wrong. That's the one that is always visible.
I think then add an animation for the same time period as the other one to phase it in, and boom. It works. It's a stupid bug. You can't get fades between activity for no good reason at all.
I discovered the alpha one myself. The first one might be what's happening. Or it could be a different class of bug altogether. But, I can assure you. I checked and did everything right. And it still failed. Obviously the work around would be to use a scene transition where they work. Perhaps not using a new activity as such at all.
There's a bunch of workarounds you could obviously come up with. Just launch the activity with the layout it's supposed to have then setup a scene to transition to the proper layout. Add in another transition to the layout yourself in the first activity. Or whatnot. But, it doesn't work. You do that transition from the fragment to the activity and the stuff will move but the fade always throws a conniption and refuses. It instantly takes on the visibility of the other view and without alpha working either, there's no way to rectify that easily either.
My original code that had something working was using scenes:
boolean to = true;
public void onClick(View view) {
Scene scene;
ViewGroup mSceneRoot = (ViewGroup) findViewById(R.id.container);
if (to) {
Transition mFadeTransition =
TransitionInflater.from(this).
inflateTransition(R.transition.transitionset);
scene = Scene.getSceneForLayout(mSceneRoot, R.layout.fragment_replacement, this);
TransitionManager.go(scene, mFadeTransition);
}
else {
Transition mFadeTransition =
TransitionInflater.from(this).
inflateTransition(R.transition.backwardstransitionset);
scene = Scene.getSceneForLayout(mSceneRoot, R.layout.fragment_rep, this);
TransitionManager.go(scene, mFadeTransition);
}
to = !to;
}
Leaving bits of old answer when I figured it was his fault for being unable to implement my clearly very brilliant idea of how to do the transition. The bug is he has no damned fade that works, and that was always the problem.
You cannot animate that merely with Z order. You change the order and they draw on top of each other rather than the other way around. To do what you're suggesting what you need to do is effectively have both orders at the same time and animate their transition with transparency.
You draw, Arc, Dog, another Arc. Then the variation in the Z-order is literally the transparency of the Arc drawn on top. If it is entirely opaque the Arc is on top of the dog. If it's entirely transparent then the Dog is over the Arc. But, if the topmost Arc is partially transparent, it'll look like the dog is melting through the arc, or arc is melting through the dog, depending on how we adjust the transparency. You can pull the same trick elsewhere. Just put the thing in both places. If it's opaque it's covered, but if it's transparent it only show the lowermost arc, and a mix of the arc with the between the objects if partially transparent. At the end of the animation, just put them in the correct order.
So during the Animation, you move the 2 Arcs to the same position always. You should see them as the same arc. And change the opacity of the Arc on top, and do whatever you're doing with that dog.
Video:
https://youtu.be/zVs3qzPU2FM
Create the layouts. Sandwich the bit you want to change height between two copies of the other object. In the one of the layouts, set the visibility to invisible. So all items are in both layouts in the same order. But, in one, the second copy of the element in question is invisible. Make sure the two copies are in the same position in both. When you change the bounds of one copy, make sure you also change the bounds of the other. Move them as a unit. When you transition the views, fade the item out while moving it around or whatnot. Since there's a second copy it won't look like a fade out, it'll look like a melt-through.
I'd like to know how I can put a silhouette on top of a camera preview. So far i've got the following example working, which just previews the Camera.
http://developer.android.com/reference/android/view/TextureView.html
I'm trying to have a Camera preview, where I got a silhouette shown so the person using the app gets an idea of where the picture should be taken, and then a button that when clicked, takes the picture, without the silhouette of course in the picture.
How can this be done? I can't seem to find any examples of how to put an overlay on top of a texture view.
Using the example in the TextureView docs you've linked, we simply create a layout XML file to hold our TextureView and overlay ImageView in a FrameLayout. We then call the Activity's setContentView() method with this layout's Resource ID, instead of the dynamically-created TextureView in the example.
The layout file, main.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextureView android:id="#+id/texture_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView android:id="#+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
android:src="#drawable/ic_launcher" />
</FrameLayout>
And the sample Activity:
public class LiveCameraActivity extends Activity
implements TextureView.SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextureView = (TextureView) findViewById(R.id.texture_view);
mTextureView.setSurfaceTextureListener(this);
}
// The TextureView.SurfaceTextureListener methods
// are the same as shown in the example.
...
}
The overlay ImageView in the layout uses the default launcher icon as its source image, as it has transparency, at least on my IDE. You would later replace this image with your silhouette. The ImageView, being listed after the TextureView, will appear on top of it, because Views are drawn with respect to their z-order in the same order they're listed in the layout, with the first View listed being on the bottom; i.e., the farthest away from you on the z-axis.
In the Activity, we're just loading the layout as the content View, and getting a reference to the TextureView created there. Everything else is the same.
I've done my searches extensively for sure, but I haven't come across exactly what I'm looking for. As such, I haven't any code to show for what I want to do. I want to know if it's possible, first of all, and then get a lead on how to implement such an action.
To keep my app simple, I'd really like to avoid starting a new activity, which seems to be involved in many of the "solutions" that I've seen.
My setup isn't anything special, just a layout with some textviews, buttons, and an image that's about as large as the screen.
I want the user to be able to click the image, and the image will "zoom" or "enlarge" to about 4-5x the size, obviously much of the image will then be off screen. Then, the user should be able to drag the image around to view the entire image as they wish. When they're done looking at the image, they should be able to click to go back to the original size.
I'm sure this will warrant a separate image for each size (one for the original, and a larger more detailed image for the enlarged version). Though, the simpler the better. If I can maintain one larger detailed image and scale it down for the standard view before it's clicked, that'd be great.
I'm assuming they'll be a click listener on the image, but I'm not sure how to do what I want without starting a new activity entirely, then upon clicking again, going back to the original activity. Can it be done in the same activity?
Thanks in advance.
EDIT:
I just had an idea. I could have the larger image in a relative view and make it invisible/gone, then make it visible upon click of the original/main image. Clicking the large image will make itself invisible/gone again. But, assuming this works, I do'nt konw how to set the action of dragging it around and boundaries to make sure you can't drag it outside of the screen entirely.
i have use this library in my project for Zooming images and its very simple to use its helps you ...
https://github.com/chrisbanes/PhotoView
JAVA:
PhotoView mImageView;
PhotoViewAttacher mAttacher;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Any implementation of ImageView can be used!
mImageView = (PhotoView) findViewById(R.id.iv_photo);
// Set the Drawable displayed
Drawable bitmap = getResources().getDrawable(R.drawable.wallpaper);
mImageView.setImageDrawable(bitmap);
// Attach a PhotoViewAttacher, which takes care of all of the zooming functionality.
mAttacher = new PhotoViewAttacher(mImageView);
}
// If you later call mImageView.setImageDrawable/setImageBitmap/setImageResource/etc then you just need to call
attacher.update();
XML:
<uk.co.senab.photoview.PhotoView
android:id="#+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp" />
In hopes that this helps someone else and that my solution will suffice in fixing someone else's issue, I'm going to answer my own question with what I found to be a good fix.
To keep it as simple as possible (as it seems that implementing such a feature requires more extensive work that I feel should be necessary), I used the method of toggling hidden/invisible views.
<FrameLayout>
<!--Main Activity-->
<LinearLayout>
<!--Primary Image-->
<ImageView
android:onClick="makeZoomVisible"/>
</LinearLayout>
<!--ScrollView Holder for Enlarged Image-->
<HorizontalScrollView
android:visibility="gone">
<!--Enlarged Image-->
<ImageView
android:onClick="makeZoomInvisible"/>
</HorizontalScrollView>
</FrameLayout>
The base layout is a Frame layout, which allows me to place the Enlarged Image holder (horizontal scroll view) on top of everything else since it comes after the main activity view (linear layout).
Once the primary image is clicked, it calls the method "makeZoomVisible", which as you may guess, toggles the visibility for the horizontal scroll view which holds the enlarged image. The image is scaled up to as large as the height of the screen allows. This works for me because my app is portrait only, and allows the image to scale up approximately 4x the size (a 2x2 of the original image size, just for comparison). Since the image maxes out at the height of the screen, there's no need to scroll/drag up and down. But the horizontal scroll allows the image to be moved side to side to view the whole image.
Clicking the enlarged image calls the method "makeZoomInvisible" which toggles its own visibility, clearing it away and allowing the user to see the main layout of the activity again.
This is the best option for me as a new Android app developer because of its simplicity. To refrain from switching activities, saving/pausing the current activity, implementing 3rd party libraries to include a horizonal+vertical scroll, or pinch zoom and drag features I'm able to achieve what I need for my app.
Hopefully this helps someone else out that may be looking for a simple solution.
I know you decided to implement simple transition yourself without using 3rd party libs. But if someone else is looking for more complex solution, I can suggest to try this library, it allows zooming from i.e. RecyclerView items to ViewPager with animation and includes zoom/pan/rotation features as well.
(Note, I'm the developer of this library)
Simple usage example:
Add regular ImageView and GestureImageView into layout:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_small"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.alexvasilkov.gestures.views.GestureImageView
android:id="#+id/image_full"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Set same image into both views:
smallImage.setImageDrawable(...);
fullImage.setImageDrawable(...);
Start animation:
fullImage.getPositionAnimator().enter(smallImage, true);
For more info see documentation and sample project.
A great way to do this would be to use a custom ImageView to handle the zooming and dragging of the image that way you can keep it in the same layout without having to start a new activity.
You should check out the TouchImageView library. It contains a custom ImageView that allows pinch zoom, double tap to zoom, dragging, and the ability to manually set the zoom of the image.
If don't want to include the full library a simple way to add this functionality would be to copy the TouchImageView java class into a package in your app (eg com.myapp.views).
Then in your xml layout instead of using:
<ImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_image" />
Change your image to use the path of the custom view class:
<com.myapp.views.TouchImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_image" />
I want to display an image preview over my app: when user presses an item in the listview (each item is a path to an image stored in sd card) image preview appears,stretched in the available space, like in this picture (image space is black, underlying app, still partially visible, is gray):
when user presses back image disappear.
I thought to make an activity just for image displaying but I don't know how to obtain the result in the picture...
Edit:
Ok here's what I've done so far:
1)Manifest:
<activity
android:name=".ImageDialogActivity" android:theme="#android:style/Theme.Dialog">
</activity>
2)Layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
3)Activity onCreate method:
super.onCreate(savedInstanceState);
setContentView(R.layout.image_preview);
String filepath = getIntent().getStringExtra("image_filepath");
((ImageView)findViewById(R.id.imageView)).setImageBitmap(getBitmap(filepath));
where getBitmap is a private method which gives me a bitmap from a filepath.
Problem is that I don't have control over dialog dimensions: dialog's width and height seem to depend on contained image ones...not to mention top/right/left/bottom margins...
Solved (maybe):
I modified layout file this way:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
>
<ImageView android:id="#+id/imageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerInside"/>
Setting width/height to a square allowed to obtain the effect...my question is: will it work for every phone?Or it is right just for mine?
Your best shot is to display your image in a Dialog
If you then want more control over the display, theme it
If you want to do this by creating a new Activity, you should set its layout parameters to wrap_content so it will appears above the other activity but not fitting the screen totally. Also by setting its theme as Theme.Dialog or an inherited theme, you 2nd activity will be a little bit darker and your activity will appear like a dialog.
You should also try to put layout parameter to fill_parent and add margins if you want the exact result as you shown (don't know if this solution could work).
this is from api demos creating an activit like a dilog try this
public class DialogActivity extends Activity {
/**
* Initialization of the Activity after it is first created. Must at least
* call {#link android.app.Activity#setContentView setContentView()} to
* describe what is to be displayed in the screen.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
// Be sure to call the super class.
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
// See assets/res/any/layout/dialog_activity.xml for this
// view layout definition, which is being set here as
// the content of our screen.
setContentView(R.layout.dialog_activity);
getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
android.R.drawable.ic_dialog_alert);
}
}
Solved, solution entered in main post seems working fine!
I'm building an Android application that will be like an eBook. Standard flip through pages, view images, etc. One of the requirements is that in multiple places you will see a preview of what a page will look like. It'll be the exact contents of that page, just in a smaller size.
I can't for the life of me get this preview working the way I need it to. I coded an activity which will display either controls to play audio or video depending on some values passed in the extras. That works fine. The preview should be this activity, but only in a smaller size, and shown in a separate activity. Here's what I've tried to get a smaller version of the activity to show:
First, I stumbled across the poorly documented ActivityGroup object. I figured I could use this to call the activity, and then get the view and throw it into a parent view somehow. Here's what that code looked like:
public class GroupTest extends ActivityGroup {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grouptest);
LocalActivityManager manager = getLocalActivityManager();
Intent intent = new Intent();
intent.setClass(getBaseContext(), ViewElement.class);
intent.putExtra("ElementID", 22);
intent.putExtra("PackID", 10);
Window w = manager.startActivity("videoelement", intent);
View v = w.getDecorView();
// Grab the table and add a view to it.
TableLayout tl = (TableLayout)findViewById(R.id.tlTest);
TableRow tr = new TableRow(this);
tr.addView(v);
tl.addView(tr);
}
}
And here's what the layout looked liked:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1"
android:id="#+id/tlTest">
</TableLayout>
This sort of worked. The activity ViewElement was indeed displaying in the GroupTest activity. The problem was that whenever I tried to add something else to the table (like a label), the ViewElement activity would disappear. I tinkered with this for a while figuring I was failing to grasp some UI constraint, then realized that the ViewElement activity being displayed had clickable buttons, which isn't what I really want. I just want to see what that page looks like, not be able to interact with it.
So I tried a different approach. Found this page on saving a view to an image: http://jtribe.blogspot.com/2008/12/saving-view-as-image-with-android.html. Sounded more like what I want.
My modified code now looks like:
public class GroupTest extends ActivityGroup {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tocrow);
LocalActivityManager manager = getLocalActivityManager();
Intent intent = new Intent();
intent.setClass(getBaseContext(), ViewElement.class);
intent.putExtra("ElementID", 22);
intent.putExtra("PackID", 10);
Window w = manager.startActivity("videoelement", intent);
View v = w.getDecorView();
Bitmap image = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.RGB_565);
v.draw(new Canvas(image));
ImageView img = (ImageView)findViewById(R.id.ivwElementPreview);
img.setImageBitmap(image);
}
}
And the layout (this is the actual layout I would be putting the previews in if I could get it working):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<ImageView
android:id="#+id/ivwElementPreview"
android:layout_width="75px"
android:layout_height="75px"
android:layout_marginRight="6dip"
android:src="#drawable/icon" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="#+id/txtElementTitle"
android:layout_width="300px"
android:layout_height="0dip"
android:layout_weight="1"
/>
<ImageView
android:id="#+id/ivwPackIcon"
android:layout_width="15px"
android:layout_height="15px"
android:layout_marginRight="6dip"
android:src="#drawable/icon" />
<ImageView
android:id="#+id/ivwPackIcon"
android:layout_width="15px"
android:layout_height="15px"
android:layout_marginRight="6dip"
android:src="#drawable/icon" />
<TextView
android:id="#+id/txtElementComments"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
/>
</LinearLayout>
</LinearLayout>
This just flat out doesn't work at all. As far as I can tell calling w.getDecorView() doesn't return a view that actually has any height, width, or drawn properties on it. If I run that code I get the error "width and height must be > 0" And if I put in values for width and height, nothing shows but a black image. So I then proceeded to create simple things such as a TextView and draw it to the bitmap to display in my LinearLayout, but could never get it working right either. I'm to the point of just being completely fed up with manipulating UI in Android.
So, has anyone else does something similar with previewing what another activity would look like, and how did you accomplish it? Am I just going down the completely wrong path here? I've googled all over the place and part of me feels like someone has to have solved this problem before, but I've lost over a day of work on it and I just can't pour much more time into it right now.
Thanks for any help.
You have to wait until the view is rendered on screen, then you can ask it to paint itself on any canvas. If the view is not showing on screen it will create an empty, 0x0 image.
If I am getting correctly, you want to place a thumbnail on your activity that is actually the preview of the activity that will be opened when this thumbnail ImageView will be clicked.
The very first time you can have a default image representing the Activity.
Next time, that is after you open this activity, you can obtain the screen shot of your activity:
Take a screenshot of a whole View
Make a thumbnail, and replace the previous thumbnail with this.