Skip to content
This repository has been archived by the owner on Jan 18, 2023. It is now read-only.

Commit

Permalink
1.35 Add ViewPager in MainActivity to swipe between 4 lists of words
Browse files Browse the repository at this point in the history
  • Loading branch information
Beginning Android committed Apr 15, 2016
1 parent d7effce commit c80d8bd
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 216 deletions.
36 changes: 0 additions & 36 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".NumbersActivity"
android:label="@string/category_numbers"
android:parentActivityName=".MainActivity">
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
<activity
android:name=".FamilyActivity"
android:label="@string/category_family"
android:parentActivityName=".MainActivity">
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
<activity
android:name=".ColorsActivity"
android:label="@string/category_colors"
android:parentActivityName=".MainActivity">
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
<activity
android:name=".PhrasesActivity"
android:label="@string/category_phrases"
android:parentActivityName=".MainActivity">
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
</application>

</manifest>
46 changes: 46 additions & 0 deletions app/src/main/java/com/example/android/miwok/CategoryAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.example.android.miwok;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

/**
* {@link CategoryAdapter} is a {@link FragmentPagerAdapter} that can provide the layout for
* each list item based on a data source which is a list of {@link Word} objects.
*/
public class CategoryAdapter extends FragmentPagerAdapter {

/**
* Create a new {@link CategoryAdapter} object.
*
* @param fm is the fragment manager that will keep each fragment's state in the adapter
* across swipes.
*/
public CategoryAdapter(FragmentManager fm) {
super(fm);
}

/**
* Return the {@link Fragment} that should be displayed for the given page number.
*/
@Override
public Fragment getItem(int position) {
if (position == 0) {
return new NumbersFragment();
} else if (position == 1) {
return new FamilyFragment();
} else if (position == 2) {
return new ColorsFragment();
} else {
return new PhrasesFragment();
}
}

/**
* Return the total number of pages.
*/
@Override
public int getCount() {
return 4;
}
}
16 changes: 0 additions & 16 deletions app/src/main/java/com/example/android/miwok/ColorsActivity.java

This file was deleted.

16 changes: 0 additions & 16 deletions app/src/main/java/com/example/android/miwok/FamilyActivity.java

This file was deleted.

72 changes: 7 additions & 65 deletions app/src/main/java/com/example/android/miwok/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.example.android.miwok;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

Expand All @@ -16,68 +13,13 @@ protected void onCreate(Bundle savedInstanceState) {
// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.activity_main);

// Find the View that shows the numbers category
TextView numbers = (TextView) findViewById(R.id.numbers);
// Find the view pager that will allow the user to swipe between fragments
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);

// Set a click listener on that View
numbers.setOnClickListener(new OnClickListener() {
// The code in this method will be executed when the numbers category is clicked on.
@Override
public void onClick(View view) {
// Create a new intent to open the {@link NumbersActivity}
Intent numbersIntent = new Intent(MainActivity.this, NumbersActivity.class);
// Create an adapter that knows which fragment should be shown on each page
CategoryAdapter adapter = new CategoryAdapter(getSupportFragmentManager());

// Start the new activity
startActivity(numbersIntent);
}
});

// Find the View that shows the family category
TextView family = (TextView) findViewById(R.id.family);

// Set a click listener on that View
family.setOnClickListener(new OnClickListener() {
// The code in this method will be executed when the family category is clicked on.
@Override
public void onClick(View view) {
// Create a new intent to open the {@link FamilyActivity}
Intent familyIntent = new Intent(MainActivity.this, FamilyActivity.class);

// Start the new activity
startActivity(familyIntent);
}
});

// Find the View that shows the colors category
TextView colors = (TextView) findViewById(R.id.colors);

// Set a click listener on that View
colors.setOnClickListener(new OnClickListener() {
// The code in this method will be executed when the colors category is clicked on.
@Override
public void onClick(View view) {
// Create a new intent to open the {@link ColorsActivity}
Intent colorsIntent = new Intent(MainActivity.this, ColorsActivity.class);

// Start the new activity
startActivity(colorsIntent);
}
});

// Find the View that shows the phrases category
TextView phrases = (TextView) findViewById(R.id.phrases);

// Set a click listener on that View
phrases.setOnClickListener(new OnClickListener() {
// The code in this method will be executed when the phrases category is clicked on.
@Override
public void onClick(View view) {
// Create a new intent to open the {@link PhrasesActivity}
Intent phrasesIntent = new Intent(MainActivity.this, PhrasesActivity.class);

// Start the new activity
startActivity(phrasesIntent);
}
});
// Set the adapter onto the view pager
viewPager.setAdapter(adapter);
}
}
16 changes: 0 additions & 16 deletions app/src/main/java/com/example/android/miwok/NumbersActivity.java

This file was deleted.

16 changes: 0 additions & 16 deletions app/src/main/java/com/example/android/miwok/PhrasesActivity.java

This file was deleted.

6 changes: 0 additions & 6 deletions app/src/main/res/layout/activity_category.xml

This file was deleted.

48 changes: 3 additions & 45 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,9 @@
android:orientation="vertical"
tools:context="com.example.android.miwok.MainActivity">

<!-- Numbers category -->
<FrameLayout
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/category_numbers">
<TextView
android:id="@+id/numbers"
style="@style/CategoryStyle"
android:background="?android:attr/selectableItemBackground"
android:text="@string/category_numbers" />
</FrameLayout>
android:layout_height="match_parent"/>

<!-- Family category -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/category_family">
<TextView
android:id="@+id/family"
style="@style/CategoryStyle"
android:background="?android:attr/selectableItemBackground"
android:text="@string/category_family" />
</FrameLayout>

<!-- Colors category -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/category_colors">
<TextView
android:id="@+id/colors"
style="@style/CategoryStyle"
android:background="?android:attr/selectableItemBackground"
android:text="@string/category_colors" />
</FrameLayout>

<!-- Phrases category -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/category_phrases">
<TextView
android:id="@+id/phrases"
style="@style/CategoryStyle"
android:background="?android:attr/selectableItemBackground"
android:text="@string/category_phrases" />
</FrameLayout>
</LinearLayout>

This comment has been minimized.

Copy link
@Bavalpreet

Bavalpreet Nov 6, 2018

after completeing all the change im having trouble with sound.

This comment has been minimized.

Copy link
@sslaia

sslaia Jun 29, 2019

The code is more complicated, but the user experience (swiping left and right) is much better.

12 comments on commit c80d8bd

@HeckJiggers
Copy link

@HeckJiggers HeckJiggers commented on c80d8bd Jul 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also change the listener behavior when AUDIOFOCUS_LOSS_TRANSIENT and AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK. We have this code:

mMediaPlayer.pause();
mMediaPlayer.seekTo(0);

which pauses the reproduction and start from the beginning when we regain audiofocus.

But, if we tap an audio, change the tab and tap a second audio, the first one start to play again when the secon ends, but out of his fragment, which I don't like. So I change the code to:

releaseMediaPlayer();

which call the method to clean up the media player.

The final code looks like this:


private AudioManager.OnAudioFocusChangeListener mOnAudioFocusChangeListener = new 
                         AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            
             if ((focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT ||
                        focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK || focusChange 
                        == AudioManager.AUDIOFOCUS_LOSS) && mMediaPlayer != null) {
                 releaseMediaPlayer();
            
            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
                 mMediaPlayer.start();
            } 
        }
    };

If you want to change it, don't forget to do it in the 4 Fragments files, NumbersFragment, FamilyFragment, ColorsFragment and PhrasesFragment.

@mohammed3296
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

releaseMediaPlayer do not work correctlu in onStop method

@HjalmarBasile
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mohqnk32 Apparently when you transition to right from the first tab (or to left from the last one) the onPause method won't be called, but the onResume of the new fragment will, so what you can do, and it worked for me, is to override both onPause and onResume, releasing the player in both of them.

@mrk-han
Copy link

@mrk-han mrk-han commented on c80d8bd Mar 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HjalmarBasile This makes sense but for some reason releaseMediaPlayer(); is not working at all for me with these fragments. I have overrided onStop, onPause, and onResume.

EDIT
Turns out ViewPager needs to keep fragments to the left and right of the current fragment so it doesn't slow down swiping!

To correctly implement releaseMediaPlayer() while swiping between fragments, check out this code:

    @Override
    public void setUserVisibleHint(boolean isVisible) {
        super.setUserVisibleHint(isVisible);

        Log.e("ColorsFragment", "setUserVisibleHint: isVisible = " + isVisible);

        if (!isVisible) {
            releaseMediaPlayer();
        }
    }

Add this code to each Fragment if you want to release while swiping! (Colors, Numbers, etc...)

For more info check out the documentation on setUserVisibleHint() here: https://developer.android.com/reference/android/support/v4/app/Fragment.html#setUserVisibleHint(boolean)

@HjalmarBasile @mohqnk32

@sherifhisham
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WOW

@mr-uaila
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I solved the problem using ViewPager's OnPageChangeListener to release the MediaPlayer at each page change: it stops the audio file rather abruptly, but I think this behavior can also make sense since when you change tabs there's no real point in continuing to play the previous audio.

@vrush96
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can only see my NumbersFragment and no other fragments y so?

@vrush96
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh Sorry i found fragments exist but no names on top please help!

@Darkthunder119
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HjalmarBasile This makes sense but for some reason releaseMediaPlayer(); is not working at all for me with these fragments. I have overrided onStop, onPause, and onResume.

EDIT
Turns out ViewPager needs to keep fragments to the left and right of the current fragment so it doesn't slow down swiping!

To correctly implement releaseMediaPlayer() while swiping between fragments, check out this code:

    @Override
    public void setUserVisibleHint(boolean isVisible) {
        super.setUserVisibleHint(isVisible);

        Log.e("ColorsFragment", "setUserVisibleHint: isVisible = " + isVisible);

        if (!isVisible) {
            releaseMediaPlayer();
        }
    }

Add this code to each Fragment if you want to release while swiping! (Colors, Numbers, etc...)

For more info check out the documentation on setUserVisibleHint() here: https://developer.android.com/reference/android/support/v4/app/Fragment.html#setUserVisibleHint(boolean)

@HjalmarBasile @mohqnk32

Nice find!

Far better than changing functionality.

The other easy solution is to release mediaPlayer resources on every change in audioFocus except Gain in the OnAudioFocusChangeListener

@LaszloLajosT
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear... Android Studio recommends import androidx support instead of android support v4. But then my app is always crash.
If anyone did this kind of changes, can tell me what else did you change to run your app?

I changed my imports to:

import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentPagerAdapter;

from:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

@qureshiwaqas
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah Im facing the same error apparently changing the imports causes issue in activity_main.xml file in view in which viewpager is defined

@qureshiwaqas
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if you change android.support.v4.view.ViewPager to androidx.viewpager.widget.ViewPager the app doesn't crash and works

Please sign in to comment.