I am currently making a chat app and i want to add a feature like telegram. As you can see here, there is a animation in the recycler view as if i=t zooming or decreasing its size. You can also notice that animation while opening and closing the navigation drawer. I too tried to do that using this but i get no animation in the recycler view. See this. Actually not this but like this. I took this gif from the README of the repo. So is that possible? If so, can you please tell me a simple implementation ?
Thanks in advance and i will be waiting 😀
Add overridePendingTransition in onBackPressed() method:
#Override
public void onBackPressed() {
super.onBackPressed();
overridePendingTransition(0, R.anim.slide_out_right);
}
res->anim->slide_out_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="#android:integer/config_mediumAnimTime"
android:fromXDelta="0"
android:toXDelta="100%p" />
</set>
To me it looks like an Activity transition where the translateZ value is modified. But since the Telegram Android client is open source, we can just take a look at it.
It looks like the Telegram devs use a lot of custom code instead of relying on the android SDK.
The DialogsActivity which extends a BaseFragment but is neither an Android Activity nor an Android Fragment since BaseFragmentdoesn't extend any of them, has the following method for the transition:
private void setSlideTransitionProgress(float progress) {
if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) {
return;
}
slideFragmentProgress = progress;
if (fragmentView != null) {
fragmentView.invalidate();
}
if (filterTabsView != null) {
float s = 1f - 0.05f * (1f - slideFragmentProgress);
filterTabsView.getListView().setScaleX(s);
filterTabsView.getListView().setScaleY(s);
filterTabsView.getListView().setTranslationX((isDrawerTransition ? AndroidUtilities.dp(4) : -AndroidUtilities.dp(4)) * (1f - slideFragmentProgress));
filterTabsView.getListView().setPivotX(isDrawerTransition ? filterTabsView.getMeasuredWidth() : 0);
filterTabsView.getListView().setPivotY(0);
filterTabsView.invalidate();
}
}
Related
I'm starting to learn how to build an Android TV for the first time so I apologize for a likely obvious answer to this question. Basically, I'm trying to replicate how the Android TV Youtube App displays when there is no internet connectivity as shown:
YouTube shows the main fragment (I believe) in the back with no videos, and there seems to be a transparent overlay with an ImageView, TextView, and Button. Once there is internet connectivity and the user taps the Retry button, it loads the video content and the overlay disappears.
I'm trying to achieve this exact same technique, and with internet connectivity, I currently have this:
With no internet connectivity, I'd like to show something similar to how YouTube does.
Here's some of my basic code:
MainActivity.java:
public class MainActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_browse_fragment"
android:name="com.ui.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ui.MainActivity"
tools:deviceIds="tv"
tools:ignore="MergeRootFrame" />
MainFragment.java:
public class MainFragment extends DetailsFragment
{
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setupUIElements();
setupThings();
}
public void setupThings()
{
if (isOnline() == true)
{
prepareBackgroundManager();
loadRows();
setupEventListeners();
}
else
{
// I don't know what to do here???
}
}
public Boolean isOnline()
{
try
{
Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
int returnVal = p1.waitFor();
boolean reachable = (returnVal == 0);
return reachable;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
Simple, if there's internet connection, I load the videos from online, otherwise, I inform the user like YouTube does.
Where I'm stuck is in the else statement. I'm not sure exactly what to create there to achieve this overlay.
I've looked at some solutions regarding switching fragments here:
Switching between Fragment view
How to switch between fragments during onclick?
However, I'm not sure if, for my purpose, I would need to do this?
Can someone point me in the right direction? I'm not looking to have someone write the whole code exactly like the YouTube app, but I'd like to have a small sample, with just maybe a Button or TextView? This will allow me to follow the structure and modify it to meet my requirements.
Thanks.
You can look at the Leanback Sample app, which contains an example of a BrowseErrorFragment.
To display:
BrowseErrorFragment errorFragment = new BrowseErrorFragment();
getFragmentManager().beginTransaction().replace(R.id.main_frame, errorFragment)
.addToBackStack(null).commit();
My animation I'snt working on click, here is my code:
Edit: can now click the button, but nothing happens on click
animation: bottom_up.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="75%p" android:toYDelta="0%p"
android:fillAfter="true"
android:duration="500"/>
here is my java MusicPlayerActivity.java:
btnPlayList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Animation bottomUp = AnimationUtils.loadAnimation(MusicPlayerActivity.this, R.anim.bottom_up);
ViewGroup hiddenPanel = (ViewGroup) v.findViewById(R.id.hidden_panel);
hiddenPanel.startAnimation(bottomUp);
hiddenPanel.setVisibility(View.VISIBLE);
}
});
}
Thank you!
check if you initialed btnPlayList
like this btnPlayList=(Button)findViewById(R.id.btnPlayList);
or hiddenPanel not exist in this view that you click on;
The error you are getting is a very common one. It's called NullPointerException because you try to call a method of an object whose reference is null, so the system can't resolve the method. You cand read more about this exception in this link.
The line that is probably causing this exception is:
ViewGroup hiddenPanel = (ViewGroup) v.findViewById(R.id.hidden_panel);
In order to fix it, I would suggest two things:
Check that the id R.id.hidden_panel is correct.
If you are contemplating that R.id.hidden_panel might not be in your layout, wrap its usage with a null check:
if (hiddenPanel != null) {
hiddenPanel.startAnimation(bottomUp);
hiddenPanel.setVisibility(View.VISIBLE);
}
EDIT:
To fix the animation not showing, try calling startAnimation after you set the hiddenPanel to Visible, and not before.
java.lang.NullPointerException -> some variables not initialized.
check all variables
In my android application I am using an ObjectAnimator to translate an imageview like so:
ObjectAnimator transitionX = ObjectAnimator.ofFloat(v, "TranslationY", 190);
Is there an option like fillAfter that will reset the position of the view to the new position, after the animation is complete?
Nope, I'd use the property animation system instead, assuming v is a view:
v.animate().translationY(190).withEndAction(new Runnable() {
#Override
public void run() {
v.setTranslationY(v.getTranslationY()-190);
}
}).start();
Nope, there is no option for that. However you can achieve the same effect using a listener where you can manually change it to the initial position in the onAnimationEnd(). Here is an example for scaling an imageview:
scaleDown.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
//Initial property values
tempIV.setScaleX(1f);
tempIV.setScaleY(1f);
tempIV.setAlpha(1f);
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
I think the right way to handle this is to use an AnimationSet to merge two animations, one to translate and one to translate back the view.
Something like this
ObjectAnimator translateTo190= ObjectAnimator.ofFloat(v, "TranslationY", 190);
ObjectAnimator translateBack = ObjectAnimator.ofFloat(v, "TranslationY", 0);
AnimatorSet translate= new AnimatorSet();
translate.play(translateTo190).before(translateBack);
translate.start();
I have had a problem like this in writing a card dealing animation where the cards are dealt quickly from a central "deck". After much trial-and-error, the way I've got this working is using the ObjectAnimator in the following way.
I add a single "deck" card at the source of the animation, and then a second card that I'm actually animating. I use the following deal_from_drawpile.xml to animate the card in two parts: the first part returns the card to the source, and the second part scales and rotates the card as it is "dealt":
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_interpolator"
android:ordering="sequentially">
<set android:interpolator="#android:anim/accelerate_interpolator"
android:ordering="together">
<objectAnimator
android:propertyName="translationX"
android:duration="10"
android:valueFrom="0.0f"
android:valueTo="0.0f"/>
<objectAnimator
android:propertyName="translationY"
android:duration="10"
android:valueFrom="0.0f"
android:valueTo="0.0f"/>
<objectAnimator
android:propertyName="scaleX"
android:duration="10"
android:valueFrom="0.75f"
android:valueTo="0.75f"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="10"
android:valueFrom="0.75f"
android:valueTo="0.75f"/>
</set>
<set android:ordering="together">
<objectAnimator
android:propertyName="rotation"
android:duration="300"
android:valueFrom="0.0f"
android:valueTo="360.0f"/>
<objectAnimator
android:propertyName="scaleX"
android:duration="300"
android:valueFrom="0.75f"
android:valueTo="0.5f"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="300"
android:valueFrom="0.75f"
android:valueTo="0.5f"/>
</set>
Then in code I add the actual translation which depends on how many hands are arranged in a rough semi-circle. The complete sequence of animations is then added in an AnimatorSet and fired off at the end. Code-snippet;
fullScreenContent.addView(dealtCardView);
for (int iCard=0; iCard<numCards; iCard++) {
for (int iPlayer = 0; iPlayer < numPlayers; iPlayer++) {
dealtCardAnimator = dealtCardAnimator.clone();
dealtCardAnimator.setTarget(dealtCardView);
//offsets where the cards are dealt according to player
ObjectAnimator playerOffsetXAnimator = ObjectAnimator.ofFloat(dealtCardView, "TranslationX", mGame.getPlayer(iPlayer).getPlayerLayout().getTranslationX());
ObjectAnimator playerOffsetYAnimator = ObjectAnimator.ofFloat(dealtCardView, "TranslationY", mGame.getPlayer(iPlayer).getPlayerLayout().getTranslationY());
if (lastDealtCardAnimator == null) dealSet.play(dealtCardAnimator).with(playerOffsetXAnimator).with(playerOffsetYAnimator);
else dealSet.play(dealtCardAnimator).with(playerOffsetXAnimator).with(playerOffsetYAnimator).after(lastDealtCardAnimator);
//The card is returned to the home point with the first portion of deal_from_drawpile
lastDealtCardAnimator = dealtCardAnimator;
}//end for iPlayer
}//end for numCards
dealSet.start();
I can now tinker with the duration of each step in the XML to get the effect I want. Note that you have to embed the duration in each element , not in the set section (where it is ignored, and some arbitrary default seems to be used instead).
I want to make an app that can create notification on the screen on top of anything that is currently being displayed. Something like the Go SMS message popup or something like the ChatHead in the following picture:
It would be even better if it is possible to draw it dynamically including touch events.What is the conventional or standard way to do this?
Example:
Like an Icon that can be clicked or dragged no matter whether you are on home screen or app drawer or other apps.Pay attention to the circular icons near the edges of the screen in the picture posted. You can drag them anywhere in any app.
What you are looking for is System Alert Window.
There's a library called StandOut! which will assist you in creating such apps.
Here is how things like Toast and dialog windows work:
In the case where just adding or bringing to front does not work, say when you are having a service add its own view to another client activity or application (FaceUnlock does this), or you cannot depend on hierarchies, you need to use the window manager and a window token to do the trick. You can then create layouts and take advantage of animations and hardware acceleration as before.
WindowManager windowManager = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.FIRST_SUB_WINDOW);
layoutParams.width = 300;
layoutParams.height = 300;
layoutParams.format = PixelFormat.RGBA_8888;
layoutParams.flags =
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
layoutParams.token = getWindow().getDecorView().getRootView().getWindowToken();
//Feel free to inflate here
mTestView = new View(this);
mTestView.setBackgroundColor(Color.RED);
//Must wire up back button, otherwise it's not sent to our activity
mTestView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackPressed();
}
return true;
}
});
windowManager.addView(mTestView, layoutParams);
Then be sure to remove the view onDestroy (or onPause) or you will crash
if (mTestView != null) {
WindowManager windowManager = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);
if (mTestView.isShown()) {
windowManager.removeViewImmediate(mTestView);
}
}
You don't need a new activity to do this. All you need to do is to add another view into your existing activity and bring it to the front, and draw/write the things that you want into that view.
If you want to do special things with this extra view, you could create your own view class
class DrawOnTop extends View {
public DrawOnTop(Context activity) {
super(activity);
}
#Override
protected void onDraw(Canvas canvas) {
// put your drawing commands here
}
}
and then you do something like
DrawOnTop mDraw = new DrawOnTop(this);
addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mDraw.bringToFront();
Then to force it to draw, you need to use mDraw.invalidate();
You could have the parent of your whole layout as RelativeLayout. The first child being the "root" of your main layout. Anything after that can be considered an overlay which is placeable to your whims.
Example:
<RelativeLayout>
<LinearLayout>
... Main Layout here ...
</LinearLayout>
<TextView left="20dip" top="20dip" text="Overlay" alpha="0.7" />
</RelativeLayout>
The best way is to start a service with your application.
Create an ImageView.
Set the LayoutParams of the Image View.
Add the view along with the params to the window manager when the service is created.
ALL SET
Your Image sticks to your window (At any screen over all apps), till you application is closed.
You can even add onclicklisteners and ontouchlisteners to the imageview.
Eg. OnClick listeners to perform some actions and Ontouchlisteners move the image along the screen.
I'm trying to create a simple app that loading photos from a website (like 9gag). I'm using jSoup and asyncTask. The problem is when I'm running the app it shows me only the urls of the images.. what can I do in order to display the image in the listView and not the urls.
XML Prob? Help :-/
![Screen Shot]https://www.dropbox.com/s/moybisjrbdgzjre/Screenshot_2013-04-29-20-09-13.png
here's my LoadImages class:
public LoadImages(ArrayList list, ArrayAdapter adapter)
{
this.list = list;
this.adapter = adapter;
}
#Override
protected Elements doInBackground(String... params) {
org.jsoup.nodes.Document doc = null;
try
{
doc =Jsoup.connect("http://mongol.co.il/").get();
return doc.select("img");
}
catch (IOException e1)
{
e1.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Elements result) {
super.onPostExecute(result);
int flag=0;
//Bitmap bitmap = null;
for ( org.jsoup.nodes.Element div : result )
{
String bla = div.absUrl("src");
list.add(bla);
flag++;
if(flag==3)
break;
}
adapter.notifyDataSetChanged();
}
Here's also my .xml file:
<?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">
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
Thanks In advance!
You're only fetching the URLs at this point. You need to fetch the actual Bitmap data in order to show images. There are two ways to do this:
Download all the images, then show the list after everything is fetched
Show the list immediately with image placeholders, the fetch the images as they're
needed
In general, it's a better experience to respond quickly by showing what you have as you get it (option #2). A ListView is really conducive to this model. In the getView() method of the adapter you'll show the placeholder image while firing off an AsyncTask to get the bitmap. You'll then set Image in onPostExecute. Unfortunately things get messy with View recycling. This basic implementation will result in the wrong image being shown in many cases and a totally unresponsive device if the user scrolls back and forth quickly.
Fortunately, these are problems that others have solved. In fact, there is an excellent set of tutorials along with sample code on Android Developer website.
I have done something like this:
I have a DB with ID, image URL, image URI
image URI is something like file:////mnt/sdcard/<your package>/images/image1.png
I have a place Holder image for each row and in my Arraylist i have put image URI in Arraylist. then in getView method check if that URI file exists or not if not then send a broadcast to download that image(with ID). In downloader I fetch images with corresponding URL.
How to check URI exists: create a file object with URI and call isExists()
How to send broadcast: create an intent put ID in extras then call sendBroadcast(intent)
Now how to refresh list after image has been download: Send another broadcast from onPostExecute() to refresh list and catch that broadcast in your activity and call list.notifyDatasetChanged().
You are adding String to the list
String bla = div.absUrl("src");
list.add(bla);
You need to create custom adapter (for the ListView), which will take that String bla and download the image.
Try this tutorial