Android : Adding a icon indicating counter in Navigation Drawer layout. - java

I am working on an Android application in which I would like to add an icon on the navigation drawer. I intend to use it for notification messages when the app is opened. The icon would receive notifications from a service, which would be running in parallel. Right now, I am struggling to put the icon in the Navigation drawer, on top right side.
Here is the screenshot of the drawer.
As you can see the red-dot, I am trying to move the red dot to upper-right hand side, which is part of the drawer and has those 3 dots vertically stacked.
Drawer code :
public class DrawerModel {
private String title;
private int icon;
private String count = "0";
private int id;
// boolean to set visiblity of the counter
private boolean isCounterVisible = false;
}
DrawerLoader :
public class DrawerLoader extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
// nav drawer title
private CharSequence mDrawerTitle;
// used to store app title
private CharSequence mTitle;
private ArrayList<DrawerModel> navDrawerItems;
private DrawerListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawerlayout);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
mDrawerLayout.closeDrawer(mDrawerList);
}
#Override
public void setTitle(CharSequence title) {
mTitle = title;
getSupportActionBar().setTitle(mTitle);
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
/* *
* Called when invalidateOptionsMenu() is triggered
*/
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// if nav drawer is opened, hide the action items
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
/**
* Slide menu item click listener
*/
private class SlideMenuClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
int sectionId = ((DrawerModel) parent.getItemAtPosition(position)).getId();
displayView(position);
Intent intent = new Intent(getApplicationContext(), GroupSectionActivity.class);
intent.putExtra("groupid", groupAccountId);
intent.putExtra("canvasid", canvasId);
intent.putExtra("sectionid", sectionId);
startActivity(intent);
}
}
#Override
public void onBackPressed() {
mDrawerLayout.closeDrawer(mDrawerList);
}
}
}
DrawerListAdapter :
public class DrawerListAdapter extends BaseAdapter {
private Context context;
private ArrayList<DrawerModel> drawerModelArrayList;
public DrawerListAdapter(Context context, ArrayList<DrawerModel> drawerModelArrayList){
this.context = context;
this.drawerModelArrayList = drawerModelArrayList;
}
#Override
public int getCount() {
return drawerModelArrayList.size();
}
#Override
public Object getItem(int position) {
return drawerModelArrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
LayoutInflater mInflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.drawout_list_item, null);
}
ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
TextView txtCount = (TextView) convertView.findViewById(R.id.counter);
icon.setImageResource(drawerModelArrayList.get(position).getIcon());
txtTitle.setText(drawerModelArrayList.get(position).getTitle());
// displaying count
// check whether it set visible or not
if(drawerModelArrayList.get(position).isCounterVisible()){
txtCount.setText(drawerModelArrayList.get(position).getCount());
}else{
// hide the counter view
txtCount.setVisibility(View.GONE);
}
return convertView;
}
}
drawerlayout.xml :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<!-- Listview to display slider menu -->
<ListView
android:id="#+id/list_slidermenu"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:dividerHeight="1dp" />
</android.support.v4.widget.DrawerLayout>
I have tried to put it directly in the XML file, but it does not work. Any help would be nice.. Thank you.. :-)

Related

Android ViewPager doesn't show Fragment

I'm trying to let my ViewPager to show my Fragments, however, it doesn't seem to do the work. All it does is just not showing anything, not even a height. Can someone tell me what step am I missing? thanks
main_activity.xml:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorBackground">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottomNavigation" />
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="#+id/bottomNavigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</android.support.design.widget.CoordinatorLayout>
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
AHBottomNavigation bottomNavigation;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigation = (AHBottomNavigation) findViewById(R.id.bottomNavigation);
viewPager = (ViewPager) findViewById(R.id.viewpager);
ViewPagerAdapter pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
// Buttom Navigation
// Add items
AHBottomNavigationItem item1 = new AHBottomNavigationItem("Rooms", R.drawable.ic_chatboxes);
AHBottomNavigationItem item2 = new AHBottomNavigationItem("User", R.drawable.ic_contact_outline);
bottomNavigation.addItem(item1);
bottomNavigation.addItem(item2);
// Customize Buttom Navigation
bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);
// Set colors
bottomNavigation.setAccentColor(ContextCompat.getColor(this, R.color.colorAccent));
bottomNavigation.setInactiveColor(ContextCompat.getColor(this, R.color.colorTabDefault));
// Set background color
bottomNavigation.setDefaultBackgroundColor(ContextCompat.getColor(this, R.color.colorBackground));
bottomNavigation.setTranslucentNavigationEnabled(true);
// Viewpager setup
pagerAdapter.addFragment(new Rooms(), "Rooms");
pagerAdapter.addFragment(new User(), "User");
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(bottomNavigation.getCurrentItem());
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
bottomNavigation.setCurrentItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
#Override
public boolean onTabSelected(int position, boolean wasSelected) {
viewPager.setCurrentItem(position, true);
return true;
}
});
}
ViewPagerAdapter.java:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
private Fragment currentItem;
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentItem() != object) {
currentItem = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
public Fragment getCurrentItem() {
return currentItem;
}
}

NullPointerException in NavDrawerListAdapter for NavigationDrawer in Android

I am having a really strange problem. I am using a NavDrawerListAdapter for my NavigationDrawer in my Android App. If the list has 13 items (NavDrawerItem), it works OK. However, when I add a 14th element, the app appears to crash and give a NullPointerException. I checked the resources,strings,etc and everything appears to be correct. The stacktrace is pointing at this class inside getView() on the following line:
imgIcon.setImageResource(navDrawerItems.get(position).getIcon());
For some reason, the imgIcon is null.
public class NavDrawerListAdapter extends BaseAdapter {
private static final String TAG = "NavDrawerListAdapter";
private Context context;
private ArrayList<NavDrawerItem> navDrawerItems;
private List<Boolean> enabledDrawerItems;
private LayoutInflater mInflater;
public NavDrawerListAdapter(Context context,
ArrayList<NavDrawerItem> navDrawerItems)
{
super();
this.context = context;
this.navDrawerItems = navDrawerItems;
this.mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
// Toggle enabled/disabled navigation drawer items
enabledDrawerItems = new ArrayList<Boolean>(Arrays.asList(new Boolean[navDrawerItems.size()]));
Collections.fill(enabledDrawerItems, new Boolean(true));
}
#Override
public int getCount() {
return navDrawerItems.size();
}
#Override
public Object getItem(int position) {
return navDrawerItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(position == 0) {
convertView = mInflater.inflate(R.layout.header_view, null);
return convertView;
}
if(convertView == null) {
// Use the drawer list item view
convertView = mInflater.inflate(R.layout.drawer_list_item, null);
}
ImageView imgIcon = (ImageView) convertView.findViewById(R.id.icon);
TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
TextView txtCounter = (TextView) convertView.findViewById(R.id.counter);
Log.d(TAG, "Position: " + position + ", Icon Resource: " + navDrawerItems.get(position).getIcon());
Log.d(TAG, "NavDrawerItems: " + navDrawerItems.size());
if(imgIcon == null){
Log.d(TAG, "imgIcon is null");
}
else{
Log.d(TAG, "imgIcon is not null");
}
imgIcon.setImageResource(navDrawerItems.get(position).getIcon());
txtTitle.setText(navDrawerItems.get(position).getTitle());
if(navDrawerItems.get(position).isCounterVisible()){
txtCounter.setText(navDrawerItems.get(position).getCount());
}
else{
txtCounter.setVisibility(View.GONE);
}
if(enabledDrawerItems.get(position) == false) {
txtTitle.setTextColor(Color.LTGRAY);
convertView.setEnabled(enabledDrawerItems.get(position));
}
return convertView;
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
return enabledDrawerItems.get(position);
}
// Set state of navigation drawer item
public void setNavigationDrawerItem(int pos, boolean enabled) {
enabledDrawerItems.set(pos, enabled);
}
}
strings.xml
<array name="nav_drawer_icons">
<item>#drawable/ic_home</item>
<item>#drawable/ic_people</item>
<item>#drawable/ic_photos</item>
<item>#drawable/ic_communities</item>
<item>#drawable/ic_pages</item>
<item>#drawable/ic_whats_hot</item>
</array>
NavigationDrawerActivity
public class NavigationDrawerActivity extends ActionBarActivity {
public DrawerLayout mDrawerLayout;
public ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
public CharSequence mDrawerTitle; // nav drawer title
public CharSequence mTitle; // store app title
public TypedArray navMenuIcons; // menu item icons
public String[] navMenuTitles; // menu item titles
public ArrayList<NavDrawerItem> navDrawerItems; // each drawer item
public NavDrawerListAdapter adapter; // nav drawer adapter
// Static Settings/Configuration
private static final int NAVIGATION_DRAWER_WIDTH_PERCENT = 85; // in percentage
private static final String TAG = "MainActivity";
public static final String INTENT_EXTRA_POSITION = "NavigationDrawerPosition";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Use ToolBar and set it as ActionBar
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
// Get Nav Menu Icons and Titles
navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_icons);
navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
// Get DrawerLayout and ListView
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.list_slidermenu);
navDrawerItems = new ArrayList<NavDrawerItem>();
addNavDrawerItems(); // add each navigation drawer item
// Recycle the array
navMenuIcons.recycle();
// setup the nav drawer list adapter
adapter = new NavDrawerListAdapter(this.getApplicationContext(), navDrawerItems);
mDrawerList.setAdapter(adapter);
mDrawerList.setOnItemClickListener(new SlideMenuClickListener());
// enabling action bar app icon and behaving it as toggle button
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
mDrawerToggle = new ActionBarDrawerToggle(this,
mDrawerLayout,
// R.drawable.ic_drawer,
R.string.app_name,
R.string.app_name)
{
public void onDrawerClosed(View view){
getSupportActionBar().setTitle(mTitle);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView){
getSupportActionBar().setTitle(mTitle);
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
Intent intent = getIntent();
if(intent != null && intent.getExtras() != null) {
int drawerPosition = intent.getExtras().getInt(INTENT_EXTRA_POSITION);
if(drawerPosition != 0) {
// update selected item, title, and close drawer
mDrawerList.setItemChecked(drawerPosition, true);
mDrawerList.setSelection(drawerPosition);
setTitle(navMenuTitles[drawerPosition-1]);
}
else {
Log.w(TAG, "drawerPosition is 0");
}
}
mDrawerTitle = getTitle();
mTitle = mDrawerTitle;
configureNavigationDrawer();
configureEnabledDisabledNavDrawItems();
}
private void configureEnabledDisabledNavDrawItems() {
// Check if Device is connected (No: disable list item, Yes: enable list item)
if(SecondScreenIAB.getInstance().getDevice() == null)
{
getAdapter().setNavigationDrawerItem(2, false);
getAdapter().setNavigationDrawerItem(3, false);
}
else
{
getAdapter().setNavigationDrawerItem(2, true);
getAdapter().setNavigationDrawerItem(3, true);
}
}
private void addNavDrawerItems() {
navDrawerItems.add(new NavDrawerItem(0, "")); // Drawer Cover Image
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(0, -1), navMenuTitles[0]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(1, -1), navMenuTitles[1]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(2, -1), navMenuTitles[2]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(3, -1), navMenuTitles[3]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(4, -1), navMenuTitles[4], "23", false));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(5, -1), navMenuTitles[5]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(0, -1), navMenuTitles[6], "5", false));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(1, -1), navMenuTitles[7]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(2, -1), navMenuTitles[8]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(3, -1), navMenuTitles[9]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(4, -1), navMenuTitles[10]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(5, -1), navMenuTitles[11]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(0, -1), navMenuTitles[12]));
navDrawerItems.add(new NavDrawerItem(navMenuIcons.getResourceId(1, -1), navMenuTitles[13]));
}
public void configureActionBar() {
SpannableString s = new SpannableString("Test");
s.setSpan(new TypefaceSpan(this, "Roboto-Regular.ttf"), 0, s.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Update the action bar title with the TypefaceSpan instance
android.support.v7.app.ActionBar actionBar = this.getSupportActionBar();
actionBar.setTitle(s);
}
private void configureNavigationDrawer() {
// Configure Navigation Drawer Width
DrawerLayout.LayoutParams params = (android.support.v4.widget.DrawerLayout.LayoutParams) mDrawerList.getLayoutParams();
params.width = (int) (getResources().getDisplayMetrics().widthPixels * (NAVIGATION_DRAWER_WIDTH_PERCENT/100.0));
mDrawerList.setLayoutParams(params);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(mDrawerToggle.onOptionsItemSelected(item)){
return true;
}
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu){
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
#Override
public void setTitle(CharSequence title) {
mTitle = title;
getSupportActionBar().setTitle(mTitle);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
public ListView getmDrawerList() {
return mDrawerList;
}
public void setmDrawerList(ListView mDrawerList) {
this.mDrawerList = mDrawerList;
}
public NavDrawerListAdapter getAdapter() {
return adapter;
}
public void setAdapter(NavDrawerListAdapter adapter) {
this.adapter = adapter;
}
}
You seem to be using two different layouts:
R.layout.header_view
R.layout.drawer_list_item
I'm guessing that "R.layout.header_view" doesn't have "R.id.icon". So when it tries to reuse it, the imgIcon is null.
Base adapter has methods
public int getItemViewType (int position)
public int getViewTypeCount ()
You have two types of views. You need to make sure item at position 0 has a different type then the rest.
You would need to add these two methods to your adapter:
#Override
public int getItemViewType (int position) {
if(position == 0)
return 0;
else
return 1;
}
#Override
public int getViewTypeCount () {
return 2;
}
And then update the first if statement in getView to:
if(position == 0) {
if(convertView == null)
convertView = mInflater.inflate(R.layout.header_view, null);
return convertView;
}
Remove header from baseAdapter do as follows in main java having your baseAdapter to add your header
View header = getLayoutInflater().inflate(R.layout.header_view, null);
ListView listView = getListView();
listView.addHeaderView(header);
listView.setAdapter(myAdapter);

Cannot Reach Breakpoint / Intent Will Not Launch

I'm attempting to launch an intent in my Home.java:
#Override
public void onVideoClicked(Video video) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(video.getUrl()));
startActivity(intent);
}
It should be initiated by:
package com.idg.omv.ui;
import com.idg.omv.domain.Video;
public interface VideoClickListener {
public void onVideoClicked(Video video);
}
which is initiated by listView.setOnVideoClickListener(this); in my Home.java
However I cannot seem to reach onVideoClicked when setting a breakpoint in Home.java and I'm unsure why.
FULL SOURCE:
public class Home extends YouTubeBaseActivity implements
VideoClickListener {
// A reference to our list that will hold the video details
private VideosListView listView;
private ActionBarDrawerToggle actionBarDrawerToggle;
public static final String API_KEY = "AIzaSyC0Te2pyooXzuyLaE6_SsFlITKCwjj55fI";
public static final String VIDEO_ID = "o7VVHhK9zf0";
private int mCurrentTabPosition = NO_CURRENT_POSITION;
private static final int NO_CURRENT_POSITION = -1;
private DrawerLayout drawerLayout;
private ListView drawerListView;
private String[] drawerListViewItems;
private ViewPager mPager;
ScrollView mainScrollView;
Button fav_up_btn1;
Button fav_dwn_btn1;
String TAG = "DEBUG THIS";
String PLAYLIST = "idconex";
Activity activity;
int imageArray[];
String[] stringArray;
private OnPageChangeListener mPageChangeListener;
ImagePagerAdapter adapter = new ImagePagerAdapter();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
final ActionBar actionBar = getActionBar();
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
viewPager.setAdapter(adapter);
actionBar.setCustomView(R.layout.actionbar_custom_view_home);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
// get list items from strings.xml
drawerListViewItems = getResources().getStringArray(R.array.items);
// get ListView defined in activity_main.xml
drawerListView = (ListView) findViewById(R.id.left_drawer);
// Set the adapter for the list view
drawerListView.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_listview_item, drawerListViewItems));
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
actionBarDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
drawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description */
R.string.drawer_close /* "close drawer" description */
);
drawerLayout.setDrawerListener(actionBarDrawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
//mainScrollView = (ScrollView) findViewById(R.id.groupScrollView);
listView = (VideosListView) findViewById(R.id.videosListView);
// Here we are adding this activity as a listener for when any row in
// the List is 'clicked'
// The activity will be sent back the video that has been pressed to do
// whatever it wants with
// in this case we will retrieve the URL of the video and fire off an
// intent to view it
listView.setOnVideoClickListener(this);
new GetYouTubeUserVideosTask(responseHandler, PLAYLIST).execute();
}
Handler responseHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
populateListWithVideos(msg);
};
};
private void populateListWithVideos(Message msg) {
Library lib = (Library) msg.getData().get(
GetYouTubeUserVideosTask.LIBRARY);
listView.setVideos(lib.getVideos());
}
#Override
protected void onStop() {
responseHandler = null;
super.onStop();
}
// This is the interface method that is called when a video in the listview
// is clicked!
// The interface is a contract between this activity and the listview
#Override
public void onVideoClicked(Video video) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(video.getUrl()));
startActivity(intent);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
actionBarDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// call ActionBarDrawerToggle.onOptionsItemSelected(), if it returns
// true
// then it has handled the app icon touch event
if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class ImagePagerAdapter extends PagerAdapter {
public ImagePagerAdapter(Activity act, int[] mImages,
String[] stringArra) {
imageArray = mImages;
activity = act;
stringArray = stringArra;
}
// this is your constructor
public ImagePagerAdapter() {
super();
// setOnPageChangeListener(mPageChangeListener);
}
private int[] mImages = new int[] { R.drawable.selstation_up_btn,
R.drawable.classical_up_btn, R.drawable.country_up_btn,
R.drawable.dance_up_btn, R.drawable.hiphop_up_btn };
private String[] stringArray = new String[] { "vevo",
"TheMozARTGROUP‎", "TimMcGrawVEVO‎", "TiestoVEVO‎",
"EminemVEVO‎" };
#Override
public int getCount() {
return mImages.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((ImageView) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Context context = Home.this;
ImageView imageView = new ImageView(context);
imageView.setImageResource(mImages[position]);
((ViewPager) container).addView(imageView, 0);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((ImageView) object);
}
private final ViewPager.SimpleOnPageChangeListener mPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(final int position) {
onTabChanged(mPager.getAdapter(), mCurrentTabPosition, position);
mCurrentTabPosition = position;
}
};
protected void onTabChanged(final PagerAdapter adapter,
final int oldPosition, final int newPosition) {
// Calc if swipe was left to right, or right to left
if (oldPosition > newPosition) {
// left to right
} else {
// right to left
View vg = findViewById(R.layout.home);
vg.invalidate();
}
final ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
int oldPos = viewPager.getCurrentItem();
#Override
public void onPageScrolled(int position, float arg1, int arg2) {
if (position > oldPos) {
// Moving to the right
} else if (position < oldPos) {
// Moving to the Left
View vg = findViewById(R.layout.home);
vg.invalidate();
}
}
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
}
});
}
}
}
VideoListView.java
public class VideosListView extends ListView implements android.widget.AdapterView.OnItemClickListener {
private List<Video> videos;
private VideoClickListener videoClickListener;
public VideosListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VideosListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VideosListView(Context context) {
super(context);
}
public void setVideos(List<Video> videos){
this.videos = videos;
VideosAdapter adapter = new VideosAdapter(getContext(), videos);
setAdapter(adapter);
// When the videos are set we also set an item click listener to the list
// this will callback to our custom list whenever an item it pressed
// it will tell us what position in the list is pressed
setOnItemClickListener(this);
}
// Calling this method sets a listener to the list
// Whatever class is passed in will be notified when the list is pressed
// (The class that is passed in just has to 'implement VideoClickListener'
// meaning is has the methods available we want to call)
public void setOnVideoClickListener(VideoClickListener l) {
videoClickListener = l;
}
#Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
}
// When we receive a notification that a list item was pressed
// we check to see if a video listener has been set
// if it has we can then tell the listener 'hey a video has just been clicked' also passing the video
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long id) {
if(videoClickListener != null){
videoClickListener.onVideoClicked(videos.get(position));
}
}
}
My Source:
https://www.dropbox.com/s/irab3x18nhj4twt/idg.zip
Working Example:
http://blog.blundell-apps.com/click-item-in-a-listview-to-show-youtube-video/
If the List has clickable elements like ImageViewand Button, when you click on the list it is consumed by the ImageView and Button and your onitemClickListener is never called.
To make it work add android:clickable="false", android:focusable="false" and
android:focusableInTouchMode="false" to each of those Buttons and ImageViews in custom adapter view.
list_item_user_video.xml
<?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="fill_parent"
android:orientation="vertical" >
<com.idg.omv.ui.widget.UrlImageView
android:id="#+id/userVideoThumbImageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/black"
android:contentDescription="YouTube video thumbnail"
android:gravity="center"
android:scaleType="fitCenter"
android:src="#drawable/ic_launcher"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"/>
<View android:layout_width="match_parent"
android:layout_height="2dp"
android:visibility="invisible"/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/userVideoTitleTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft = "5dip"
android:textSize="16sp"
android:text="Video Title Not Found"
android:textColor="#android:color/black" />
<TextView
android:id="#+id/userVideouploaderTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="13sp"
android:paddingLeft = "5dip"
android:layout_below="#id/userVideoTitleTextView"
android:textColor="#android:color/black" />
<Button
android:id="#+id/fav_up_btn1"
android:layout_width="27dp"
android:layout_height="27dp"
android:layout_alignParentRight="true"
android:background="#drawable/fav_up_btn1"
android:gravity="right"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"/>
</RelativeLayout>
<View android:layout_width="match_parent"
android:layout_height="11dp"
android:visibility="invisible"/>
</LinearLayout>
Checkout this article for more info
List view doesn't respond to click

ViewPager.SimpleOnPageChangeListener Does Not Function

I have a ViewPager / PagerAdapter which should allow me to swipe through a series of footer images in order to change the station (by changing the string PLAYLIST):
...however when I swipe through the images - nothing seems to happen.
Any suggestions are greatly appreciated!
SOURCE:
public class Home extends YouTubeBaseActivity implements
VideoClickListener {
private VideosListView listView;
private ActionBarDrawerToggle actionBarDrawerToggle;
public static final String API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
public static final String VIDEO_ID = "o7VVHhK9zf0";
private int mCurrentTabPosition = NO_CURRENT_POSITION;
private static final int NO_CURRENT_POSITION = -1;
private DrawerLayout drawerLayout;
private ListView drawerListView;
private String[] drawerListViewItems;
private ViewPager mPager;
ScrollView mainScrollView;
Button fav_up_btn1;
Button fav_dwn_btn1;
String TAG = "DEBUG THIS";
String PLAYLIST = "EminemVEVO‎";
private OnPageChangeListener mPageChangeListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
final ActionBar actionBar = getActionBar();
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
ImagePagerAdapter adapter = new ImagePagerAdapter();
viewPager.setAdapter(adapter);
actionBar.setCustomView(R.layout.actionbar_custom_view_home);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
drawerListViewItems = getResources().getStringArray(R.array.items);
drawerListView = (ListView) findViewById(R.id.left_drawer);
drawerListView.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_listview_item, drawerListViewItems));
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
actionBarDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
drawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description */
R.string.drawer_close /* "close drawer" description */
);
drawerLayout.setDrawerListener(actionBarDrawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
mainScrollView = (ScrollView) findViewById(R.id.groupScrollView);
listView = (VideosListView) findViewById(R.id.videosListView);
listView.setOnVideoClickListener(this);
new GetYouTubeUserVideosTask(responseHandler, PLAYLIST).execute();
}
Handler responseHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
populateListWithVideos(msg);
};
};
private void populateListWithVideos(Message msg) {
Library lib = (Library) msg.getData().get(
GetYouTubeUserVideosTask.LIBRARY);
listView.setVideos(lib.getVideos());
}
#Override
protected void onStop() {
responseHandler = null;
super.onStop();
}
#Override
public void onVideoClicked(Video video) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(video.getUrl()));
startActivity(intent);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
actionBarDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class ImagePagerAdapter extends PagerAdapter {
public ImagePagerAdapter() {
super();
}
private int[] mImages = new int[] { R.drawable.selstation_up_btn,
R.drawable.classical_up_btn, R.drawable.country_up_btn,
R.drawable.dance_up_btn, R.drawable.hiphop_up_btn };
#Override
public int getCount() {
return mImages.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((ImageView) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Context context = Home.this;
ImageView imageView = new ImageView(context);
imageView.setImageResource(mImages[position]);
((ViewPager) container).addView(imageView, 0);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((ImageView) object);
}
private final ViewPager.SimpleOnPageChangeListener mPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(final int position) {
onTabChanged(mPager.getAdapter(), mCurrentTabPosition, position);
mCurrentTabPosition = position;
}
};
protected void onTabChanged(final PagerAdapter adapter,
final int oldPosition, final int newPosition) {
if (oldPosition > newPosition) {
// left to right
} else {
// right to left
String PLAYLIST = "TimMcGrawVEVO‎";
View vg = findViewById(R.layout.home);
vg.invalidate();
}
final ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
int oldPos = viewPager.getCurrentItem();
#Override
public void onPageScrolled(int position, float arg1, int arg2) {
if (position > oldPos) {
// Moving to the right
} else if (position < oldPos) {
// Moving to the Left
String PLAYLIST = "TimMcGrawVEVO‎";
View vg = findViewById(R.layout.home);
vg.invalidate();
}
}
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
}
});
}
}
}
You're not adding the Listener to your Pager.
You need to call setOnPageChangeListener(mPageChangeListener) on your pagerAdapter.
For example in the Constructor:
public ImagePagerAdapter(){
super();
setOnPageChangeListener(mPageChangeListener);
}
for more info, check the docs. http://developer.android.com/reference/android/support/v4/view/ViewPager.html

Call NavigationDrawer in ALL Activitys

I have a NavigationDrawer and I would call it more Activity without having to copy and paste the same code in different classes. Thus, all the code that I would have to paste in the various classes, I put it in a class of its own, called NavDrawer. Here is the code.
NavDrawer
public class NavDrawer extends Activity{
ListView mDrawerList;
DrawerLayout mDrawer;
CustomActionBarDrawerToggle mDrawerToggle;
String[] menuItems;
Intent intent, intent2, intent3, intent4, intent5, intent6;
public void _initMenu() {
NsMenuAdapter mAdapter = new NsMenuAdapter(this);
// Add Header
mAdapter.addHeader(R.string.ns_menu_main_header);
// Add first block
menuItems = getResources().getStringArray(
R.array.ns_menu_items);
String[] menuItemsIcon = getResources().getStringArray(
R.array.ns_menu_items_icon);
int res = 0;
for (String item : menuItems) {
int id_title = getResources().getIdentifier(item, "string",
this.getPackageName());
int id_icon = getResources().getIdentifier(menuItemsIcon[res],
"drawable", this.getPackageName());
NsMenuItemModel mItem = new NsMenuItemModel(id_title, id_icon);
mAdapter.addItem(mItem);
res++;
}
mDrawerList = (ListView) findViewById(R.id.drawer);
if (mDrawerList != null)
mDrawerList.setAdapter(mAdapter);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawer.isDrawerOpen(mDrawerList);
//menu.findItem(R.id.item1).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
/*
* The action bar home/up should open or close the drawer.
* ActionBarDrawerToggle will take care of this.
*/
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
private class CustomActionBarDrawerToggle extends ActionBarDrawerToggle {
public CustomActionBarDrawerToggle(Activity mActivity,DrawerLayout mDrawerLayout){
super(
mActivity,
mDrawerLayout,
R.drawable.ic_drawer,
R.string.ns_menu_open,
R.string.ns_menu_close);
}
#Override
public void onDrawerClosed(View view) {
getActionBar().setTitle(getString(R.string.ns_menu_close));
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
#Override
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(getString(R.string.ns_menu_open));
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
}
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Highlight the selected item, update the title, and close the drawer
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
if(position==0) {
//Open an Activity
}
if(position==1) {
//Open an Activity
}
if(position==2) {
//Open an Activity
}
//You should reset item counter
mDrawer.closeDrawer(mDrawerList);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.examplelayout);
getActionBar().setDisplayHomeAsUpEnabled(true);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
_initMenu();
mDrawerToggle = new CustomActionBarDrawerToggle(this, mDrawer);
mDrawer.setDrawerListener(mDrawerToggle);
_initMenu();
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
}
}
NsMenuAdapter
public class NsMenuAdapter extends ArrayAdapter<NsMenuItemModel> {
public NsMenuAdapter(Context context) {
super(context, 0);
}
public void addHeader(int title) {
add(new NsMenuItemModel(title, -1, true));
}
public void addItem(int title, int icon) {
add(new NsMenuItemModel(title, icon, false));
}
public void addItem(NsMenuItemModel itemModel) {
add(itemModel);
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
return getItem(position).isHeader ? 0 : 1;
}
#Override
public boolean isEnabled(int position) {
return !getItem(position).isHeader;
}
public static class ViewHolder {
public final TextView textHolder;
public final ImageView imageHolder;
public final TextView textCounterHolder;
public ViewHolder(TextView text1, ImageView image1,TextView textcounter1) {
this.textHolder = text1;
this.imageHolder = image1;
this.textCounterHolder=textcounter1;
}
}
public View getView(int position, View convertView, ViewGroup parent) {
NsMenuItemModel item = getItem(position);
ViewHolder holder = null;
View view = convertView;
if (view == null) {
int layout = R.layout.ns_menu_row_counter;
if (item.isHeader)
layout = R.layout.ns_menu_row_header;
view = LayoutInflater.from(getContext()).inflate(layout, null);
TextView text1 = (TextView) view.findViewById(R.id.menurow_title);
ImageView image1 = (ImageView) view.findViewById(R.id.menurow_icon);
TextView textcounter1 = (TextView) view.findViewById(R.id.menurow_counter);
view.setTag(new ViewHolder(text1, image1,textcounter1));
}
Object tag = view.getTag();
if (tag instanceof ViewHolder) {
holder = (ViewHolder) tag;
}
if(item != null && holder != null)
{
if (holder.textHolder != null)
holder.textHolder.setText(item.title);
if (holder.textCounterHolder != null){
if (item.counter > 0){
holder.textCounterHolder.setVisibility(View.VISIBLE);
}else{
holder.textCounterHolder.setVisibility(View.GONE);
}
}
if (holder.imageHolder != null) {
if (item.iconRes > 0) {
holder.imageHolder.setVisibility(View.VISIBLE);
holder.imageHolder.setImageResource(item.iconRes);
} else {
holder.imageHolder.setVisibility(View.GONE);
}
}
}
return view;
}
}
NsMenuItemModel
public class NsMenuItemModel {
public int title;
public int iconRes;
public int counter;
public boolean isHeader;
public NsMenuItemModel(int title, int iconRes,boolean header,int counter) {
this.title = title;
this.iconRes = iconRes;
this.isHeader=header;
this.counter=counter;
}
public NsMenuItemModel(int title, int iconRes,boolean header){
this(title,iconRes,header,0);
}
public NsMenuItemModel(int title, int iconRes) {
this(title,iconRes,false);
}
}
In classes where I want to have the NavigationDrawer I do nothing but extend the class NavigationDrawer, so I have a code like this
public class ExampleClass extends NavDrawer
And when I run the application in the ActionBar visualize the image and NavigationDrawer displayed but is EMPTY. Why?
In addition, in the onCreate of the class NavDrawer I set layout as the layout of an Activity, but if I have to see it in ALL Activity, can not be linked to ONE that A specific layout specific Activity. So I thought I'd create one specifically for the NavigationDrawer, containing one and only its structure. code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- The navigation drawer -->
<ListView
android:id="#+id/drawer"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#F3F3F4"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" >
</ListView>
</android.support.v4.widget.DrawerLayout>
It can work or not?
The layout of the example has a structure similar to this
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
<!-- The navigation drawer -->
<ListView
android:id="#+id/drawer"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#F3F3F4"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" >
</ListView>
</android.support.v4.widget.DrawerLayout>
I hope to have answers to all these and I apologize if my questions may seem trivial but are days that I am looking desperately for a solution, but I just can not. I hope to get answers and help. Thanks in advance.

Categories

Resources