Android: Shared transition only opens activity without animation - android

I want to create a shared transition for my app, but it doesn't work like it should. It should make that fancy animation before the next activity appears, but it only opens it. And the image doesn't show there too. I have this code:
public void loadContent(final List<Post> posts){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
ListAdapter adapter = new ListAdapter(posts, new View.OnClickListener(){
#Override
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, PostViewActivity.class);
ImageView placeImage = (ImageView)v.findViewById(R.id.postPhoto);
TextView textView = (TextView)v.findViewById(R.id.textText);
Pair<View, String> imagePair = Pair.create((View) placeImage, getString(R.string.transition_image));
Pair<View, String> holderPair = Pair.create((View) textView, getString(R.string.transition_username));
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, imagePair, holderPair);
//ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, holderPair);
ActivityCompat.startActivity(MainActivity.this, intent, options.toBundle());
}
});
RecyclerView rv = (RecyclerView)findViewById(R.id.post_list);
StaggeredGridLayoutManager lm = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
rv.setLayoutManager(lm);
rv.setAdapter(adapter);
}
});
And these two XML files:
id:orientation="vertical"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:paddingTop="0px"
android:id="#+id/postPhoto"
android:transitionName="#string/transition_image"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/colorAccent"
android:id="#+id/usernameText"
android:transitionName="#string/transition_username"/>
And the other XML file:
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionName="#string/transition_image"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionName="#string/transition_username"/>
It only opens the new activity, but not with the Image and the text. I tried it also only with the image. What's wrong?

Related

Button needs to get clicked twice

I want to get familiar with Android and started taking some Udacity courses. Currently, we have to make an ImageButton play some audio on click for language-learning purposes.
I thought it would be nice if the button toggled as well, for example, in a paused state, it should display a "play" icon and in a playing state, a "pause" icon. This is very simple to achieve using an OnClickListener and it also works properly, up to 1 small detail: the user has to click the button twice.
After some searching, I found out that the first click is used to focus the view in that position and the second view is when the fired OnClickEvent is actually handled. I tried to change the focusable and focusableInTouchModeattributes to all possible combinations in all possible places, but it didn't work.
Here is my main Activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView numbersView = findViewById(R.id.numbers);
numbersView.setOnClickListener(v -> {
Intent numbersIntent = new Intent(MainActivity.this, NumbersActivity.class);
startActivity(numbersIntent);
});
TextView familyView = findViewById(R.id.family);
familyView.setOnClickListener(v -> {
Intent familyIntent = new Intent(MainActivity.this, FamilyActivity.class);
startActivity(familyIntent);
});
TextView colorView = findViewById(R.id.colors);
colorView.setOnClickListener(v -> {
Intent colorsIntent = new Intent(MainActivity.this, ColorActivity.class);
startActivity(colorsIntent);
});
TextView phrasesView = findViewById(R.id.phrases);
phrasesView.setOnClickListener(v -> {
Intent phrasesIntent = new Intent(MainActivity.this, PhrasesActivity.class);
startActivity(phrasesIntent);
});
}
}
Here is the corresponding xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity"
android:orientation="vertical"
android:divider="?android:dividerHorizontal"
android:showDividers="middle"
android:background="#212121">
<TextView
android:id="#+id/numbers"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/numbers"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#b794f6"/>
<TextView
android:id="#+id/family"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/family"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#90CAF9"/>
<TextView
android:id="#+id/colors"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/colors"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#EEEEEE"/>
<TextView
android:id="#+id/phrases"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/phrases"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#FFE082"/>
Here is my NumbersActivity (the other activities are very much alike):
public class NumbersActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.word_list);
ListView view = findViewById(R.id.coolList);
List<Word> words = new ArrayList<>(Arrays.asList(
new Word("lutti", "one", R.drawable.number_one, R.raw.test_audio),
new Word("otiiko", "two", R.drawable.number_two, R.raw.test_audio),
new Word("tolookosu", "three", R.drawable.number_three, R.raw.test_audio),
new Word("oyyisa", "four", R.drawable.number_four, R.raw.test_audio),
new Word("massokka", "five", R.drawable.number_five, R.raw.test_audio),
new Word("temmokka", "six", R.drawable.number_six, R.raw.test_audio),
new Word("kenekaku", "seven", R.drawable.number_seven, R.raw.test_audio),
new Word("kawinta", "eight", R.drawable.number_eight, R.raw.test_audio),
new Word("wo'e", "nine", R.drawable.number_nine, R.raw.test_audio),
new Word("na'aacha", "ten", R.drawable.number_ten, R.raw.test_audio)));
WordAdapter itemsAdapter = new WordAdapter(this, words, getColor(R.color.numbers_category));
view.setAdapter(itemsAdapter);
}
}
//I know that doing it like this isn't that great, I just needed to get something up and running and worry about these changes later.
Here is the xml to that:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/coolList"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:divider="#B0BEC5"
android:dividerHeight="2dp"
android:background="#212121"
android:focusable="false"
android:focusableInTouchMode="false"></ListView>
Here is the Word Class:
public class Word {
private String miwokTranslation;
private String defaultTranslation;
private int ressourceID = -1; //just init, in order to check for it later
private int audioID;
public Word(String miwokTranslation, String defaultTranslation, int ressourceID, int audioID) {
this.miwokTranslation = miwokTranslation;
this.defaultTranslation = defaultTranslation;
this.ressourceID = ressourceID;
this.audioID = audioID;
}
public Word(String miwokTranslation, String defaultTranslation, int audioID) {
this.miwokTranslation = miwokTranslation;
this.defaultTranslation = defaultTranslation;
this.audioID = audioID;
}
public String getMiwokTranslation() {
return miwokTranslation;
}
public String getDefaultTranslation() {
return defaultTranslation;
}
public int getResourceID() {
return ressourceID;
}
public int getAudioID() {
return audioID;
}
#Override
public String toString() {
return miwokTranslation + "\n" + defaultTranslation;
}
}
Here is the corresponding Adapter:
public class WordAdapter extends ArrayAdapter<Word> {
private final int color;
Context context;
public WordAdapter(#NonNull Context context, #NonNull List<Word> objects, int color) {
super(context, 0, objects);
this.color = color;
this.context = context;
}
#RequiresApi(api = Build.VERSION_CODES.O)
#SuppressLint("ClickableViewAccessibility")
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
Word item = getItem(position);
ImageView image = convertView.findViewById(R.id.list_item_icon);
if(item.getResourceID() == -1) {
image.setVisibility(View.GONE);
} else {
image.setImageResource(item.getResourceID());
}
TextView miwokWord = convertView.findViewById(R.id.miwok_word);
miwokWord.setText(item.getMiwokTranslation());
miwokWord.setTextColor(color);
TextView defaultWord = convertView.findViewById(R.id.default_word);
defaultWord.setText(item.getDefaultTranslation());
defaultWord.setTextColor(color);
ImageButton button = convertView.findViewById(R.id.imageButton);
MediaPlayer mediaPlayer = MediaPlayer.create(context, item.getAudioID());
button.setOnClickListener(v -> {
if (!mediaPlayer.isPlaying()) {
button.setImageResource(R.drawable.play_icon);
mediaPlayer.start();
} else {
button.setImageResource(R.drawable.pause_icon);
mediaPlayer.pause();
}
});
return convertView;
}
}
The Annotations are these due to previous efforts and I didn't remove them, in case i'd need them again.
Last but not least, here is the xml of the adapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:minHeight="?android:attr/listPreferredItemHeight"
android:padding="16dp"
android:focusable="true"
android:focusableInTouchMode="false">
<ImageView
android:id="#+id/list_item_icon"
android:layout_width="88dp"
android:layout_height="88dp"
android:contentDescription="#string/magic"
android:background="#424242"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="16dp"
tools:ignore="RtlSymmetry">
<TextView
android:id="#+id/miwok_word"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:textStyle="bold"/>
<TextView
android:id="#+id/default_word"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
<ImageButton
android:id="#+id/imageButton"
android:layout_width="73dp"
android:layout_height="match_parent"
android:contentDescription="#string/playsound"
android:src="#drawable/play_icon"/></LinearLayout>
I have been sitting on this for some good couple of hours by now without any significant progress and at this Point i don't have any clues about what to do next.
Any Help would be appreciated.
Thanks in Advance
Not sure why you concluded that focus has anything to do with your problem.
If the default beginning state of the icon is android:src="#drawable/play_icon" and the default beginning state of the mediaPlayer is "not playing", wouldn't the first click result in button.setImageResource(R.drawable.play_icon); which just...sets the play icon again? So the first click changes the icon from play to play, and the second sets it from play to pause.
Have you tried debugging your code with a breakpoint? Set one in your click listener and see what happens.

Flickering(Blinking) screen when using Shared elements animation to change between activities

I'm developing an android app and using a shared element transition between the splash screen activity and my login activity. while the transition is happening i get to see the background of my phone, apps and everthing, the only thing that i can see from my application is the logo animation, everything else, gone.
Here is my code:
Splash Screen (Origin)
<LinearLayout
android:id="#+id/meofat_logo"
android:layout_width="86dp"
android:layout_height="86dp"
android:layout_gravity="center"
android:background="#drawable/meofat_logo"
android:orientation="vertical"
android:layout_marginTop="210dp"
android:elevation="24dp"
android:transitionName="logo"/>
<LinearLayout
android:id="#+id/meofat_tipo"
android:layout_width="160dp"
android:layout_height="50dp"
android:background="#drawable/meofat_tipo"
android:layout_gravity="center"
android:elevation="24dp"
android:transitionName="tipo"/>
Login Screen (Destination)
<LinearLayout
android:id="#+id/meofat_logo"
android:layout_width="58dp"
android:layout_height="58dp"
android:layout_gravity="center"
android:background="#drawable/meofat_logo"
android:orientation="vertical"
android:layout_marginTop="80dp"
android:elevation="24dp"
android:transitionName="logo"/>
<LinearLayout
android:id="#+id/meofat_tipo"
android:layout_width="106dp"
android:layout_height="33dp"
android:background="#drawable/meofat_tipo"
android:layout_gravity="center"
android:elevation="24dp"
android:transitionName="tipo"/>
SplashScreen Code:
public class RedirectActivity extends Activity {
private static int SPLASH_TIME_OUT = 2000;
LinearLayout logo,tipo;
Animation upToDown;
Animation downToUp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_redirect);
logo = (LinearLayout) findViewById(R.id.meofat_logo);
tipo = (LinearLayout) findViewById(R.id.meofat_tipo);
upToDown = AnimationUtils.loadAnimation(this,R.anim.uptodown);
logo.setAnimation(upToDown);
downToUp = AnimationUtils.loadAnimation(this,R.anim.downtoup);
tipo.setAnimation(downToUp);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
MEOFatSession session = new MEOFatSession(RedirectActivity.this);
if (session.isLoggedIn()){
Intent goToMeasurement = new Intent(RedirectActivity.this,
MeasurementActivity.class);
RetrofitInitializer.getInstance().addCredentials(session.getCredentials());
startActivity(goToMeasurement);
finish();
} else {
Intent goToLogin = new Intent(RedirectActivity.this,
LoginActivity.class);
ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.
makeSceneTransitionAnimation(RedirectActivity.this,findViewById(R.id.meofat_logo),
"logo");
startActivity(goToLogin, optionsCompat.toBundle());
finish();
}
}
},SPLASH_TIME_OUT);
}
}
A gif trying to illustrate the problem.
https://giphy.com/gifs/d1G6hKgTAsX5hOo0
Removing the finish() method solved the issue. Apparently it would destroy the activity during the animation causing it to vanish.
Like #GaboSampaio said, finish() caused the flickering. You can delay it :
Handler handler = new Handler();
handler.postDelayed(this::finish, 1000);
Intent goToLogin = new Intent(RedirectActivity.this, LoginActivity.class);
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
RedirectActivity.this,
// Now we provide a list of Pair items which contain the view we can transitioning
// from, and the name of the view it is transitioning to, in the launched activity
new Pair<View, String>(findViewById(R.id.logo_splash),
"tipo"));
ActivityCompat.startActivity(RedirectActivity.this, intent, activityOptions.toBundle());

Transition animation starting position wrong place

I'm having problems with android transition. I have a recyclerview list with multiple elements. The animation should start from any row's image when clicked, but it doesn't, it starts from the middle of the row.
I have a fragment with a RecyclerView, here is where the transition begins
fragment_states:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="namespace.fragments.StatesFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerViewStates"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?attr/actionBarSize"
/>
</FrameLayout>
The previous recyclerView has a list adapter where a row is defined as shown below. Here I defined android:transitionName="stateImage", is the image from where the transition should start.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imgState"
android:layout_width="60dp"
android:layout_height="60dp"
android:transitionName="stateImage"
android:padding="6dp" />
<TextView
android:padding="10dp"
android:layout_toRightOf="#id/imgState"
android:id="#+id/txtNombreEstado"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
/>
</RelativeLayout>
Here's how I call the transition:
StatesFragment.java
public class StatesFragment extends Fragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
recyclerView.addOnItemTouchListener(new Helper.RecyclerTouchListener(getActivity(), recyclerView, new Helper.ClickListener() {
#Override
public void onClick(View view, int position) {
try {
Intent intent = new Intent(getActivity(), CitiesActivity.class);
//Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Call some material design APIs here
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(getActivity(), view, "stateImage");
startActivity(intent, options.toBundle());
} else {
// Implement this feature without material design
startActivity(intent);
}
}
catch (Exception ex)
{
}
}
#Override
public void onLongClick(View view, int position) {
}
}));
}
Any idead on what I'm doing wrong?
My mistake was in this line:
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(getActivity(), view, "stateImage");
I was passing the view, in this case the row. This is how I fixed it
final ImageView image = (ImageView)
view.findViewById(R.id.stateImage);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(getActivity(), image, "stateImage");

Position View X Y and translate animation to an Original location

I am trying to do an animation where the small circle goes to the next screen as soon as it is clicked. I have a custom list view, with two text views. One of the textview is in circle background.
Now on click event for listitem the following code is triggered :
Intent intent = new Intent(v.getContext(), DetailActivity.class);
int[] location = new int[2];
holder.initialView.getLocationInWindow(location);
intent.putExtra("location", location);
intent.putExtra("initialText", holder.initialView.getText());
context.startActivity(intent);
In the above code I am getting the location in windows of initialTextView, i.e. with circle background, and then pass the same to DetailActivity.
Inside of detailActivity, OnResume, I have the following code:
private TextView mInitialTextView;
private String mInitialText;
private int[] listItemLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
listItemLocation = getIntent().getIntArrayExtra("location");
mInitialText = getIntent().getStringExtra("initialText");
mInitialTextView = (TextView) findViewById(R.id.initial);
}
#Override
protected void onResume() {
super.onResume();
mInitialTextView.post(new Runnable() {
#Override
public void run() {
int[] location = new int[2];
mInitialTextView.getLocationOnScreen(location);
float x = location[0];
float y = location[1];
mInitialTextView.setX(listItemLocation[0]);
mInitialTextView.setY(listItemLocation[1]);
mInitialTextView.setText(mInitialText);
mInitialTextView.animate().translationX(x)
.translationY(y).setDuration(1000).setStartDelay(100);
}
});
}
DetailActivity - Layout file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.architectpack.animate.DetailActivity">
<TextView
android:id="#+id/initial"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:layout_gravity="center"
android:gravity="center"
android:text="AM"
android:background="#drawable/circle_background" />
</RelativeLayout>
However, it not working. It is not calculating positions correctly.
Any help is appreciated.

Using multiple views in android

So I have the following onCreate function
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mylocation = new MyLocation(this);
double distance = distance (mylocation.lat, mylocation.lng, messagelat, messagelong);
Log.d("Distance",Double.toString(distance));
mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
mView = new SampleView(this,Double.toString(distance));
**this.setContentView(R.layout.activity_clouds);**
this.button = (Button)this.findViewById(R.id.close);
this.button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent myIntent = new Intent(Activity1.this, CameraPreview.class);
Activity1.this.startActivity(myIntent);
}
});
**setContentView(mView);**
}
My problem is that I want to use both view the one from activity_cloud.xml and the SampleView but If I do it this way I only get the sample view! I want to add a button over and overlay that is implemented in the SampleView class... Thanks a lot
You can use your custom view within regular xml layouts.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<com.something.something.SampleView
android:id="#+id/sample_view"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<Button android:layout_height="0dp"
android:layout_width="fill_parent"
android:layout_weight="1"
android:id="#+id/close"/>

Categories

Resources