Aliot
Aliot

Reputation: 3

ViewPager not updating from code, android, eclipse

After searching through a lot of answer here, i cant seem to solve my problem. First i had a problem using findViewById to get a listView from a fragment, to solve this i had to inflate the layout of the fragment first and use "mContainer.findViewById..".

I don't know if that is the cause of the viewpager not updating (or the listview itself).

My OnCreate:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    myContainer = getLayoutInflater().inflate(R.layout.frag_links,null);


    root = (RelativeLayout) findViewById(R.id.rootLayout);
    root.post(new Runnable() { 




        @Override
        public void run() { 
            Rect rect = new Rect(); 
            Window win = getWindow();  // Get the Window
            win.getDecorView().getWindowVisibleDisplayFrame(rect); 
            // Get the height of Status Bar 
            int statusBarHeight = rect.top; 
            // Get the height occupied by the decoration contents 
            int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop(); 
            // Calculate titleBarHeight by deducting statusBarHeight from contentViewTop  
            int titleBarHeight = contentViewTop - statusBarHeight; 
            Log.i("MY", "titleHeight = " + titleBarHeight + " statusHeight = " + statusBarHeight + " contentViewTop = " + contentViewTop); 

            // By now we got the height of titleBar & statusBar
            // Now lets get the screen size
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);   
            screenHeight = metrics.heightPixels;
            screenWidth = metrics.widthPixels;
            Log.i("MY", "Actual Screen Height = " + screenHeight + " Width = " + screenWidth);   

            // Now calculate the height that our layout can be set
            // If you know that your application doesn't have statusBar added, then don't add here also. Same applies to application bar also 
            int layoutHeight = screenHeight - (titleBarHeight + statusBarHeight);
            Log.i("MY", "Layout Height = " + layoutHeight);   

            // Lastly, set the height of the layout       
            //           LinearLayout.LayoutParams rootParams = (android.widget.LinearLayout.LayoutParams)root.getLayoutParams();
            //           rootParams.height = layoutHeight;
            //           root.setLayoutParams(rootParams);      
        } 
    });

    // (array => res/values/strings)
    titulosMenu = getResources().getStringArray(R.array.drawer_items);


    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);


    lvdrawer = (ListView) findViewById(R.id.lvdrawer);
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);


    View header = getLayoutInflater().inflate(R.layout.header, null);

    lvdrawer.addHeaderView(header);


    itemsMenu = new ArrayList<ItemDrawer>();

    for (int i = 0; i < titulosMenu.length; i++) {
        itemsMenu.add(new ItemDrawer(titulosMenu[i]));
    }

    AdaptadorDrawer adapter=new AdaptadorDrawer(this, R.layout.filaitem, itemsMenu);


    lvdrawer.setAdapter(adapter);

    lvdrawer.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> a, View v, int posicion,
                long id) {
            Intent intent;

            switch (posicion) {
            //                  case 1:
                //                      break;
            //                  case 2:
            //                      break;
            case 3:
                intent = new Intent(MainActivity.this, Contacto.class);
                startActivity(intent);
                break;
            }
            drawerLayout.closeDrawers();
        }
    });


    drawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
            GravityCompat.START);


    toggle = new ActionBarDrawerToggle(this, // Activity
            drawerLayout, // Panel del Navigation Drawer
            new Toolbar(MainActivity.this), // Icono que va a utilizar
            R.string.menu, // Descripcion al abrir el drawer
            R.string.app_name // Descripcion al cerrar el drawer
            ) {
        @Override
        public void onDrawerOpened(View drawerView) {

            getActionBar().setTitle(R.string.menu);

            invalidateOptionsMenu();
        }

        @Override
        public void onDrawerClosed(View view) {

            getActionBar().setTitle(TITULOREEM);
            invalidateOptionsMenu();
        }
    };

    drawerLayout.setDrawerListener(toggle);


        pager = (ViewPager)findViewById(R.id.viewPager);
        pager.setAdapter(new AdaptadorPager(getSupportFragmentManager()));


        TitlePageIndicator titleIndicator = (TitlePageIndicator)findViewById(R.id.titulo);
        titleIndicator.setViewPager(pager);
        LinearNews=(LinearLayout)findViewById(R.id.LinearNoticias);

        putLinks();
    }

}

Here is the problem, i call this method but nothing happens. if i dont use myContainer.findViewById the program will crash showing a nullpointerexception as it couldnt find the ListView:

private void putLinks() {

    lvLinks = (ListView)myContainer.findViewById(R.id.lvlinksnuevo);

    listaLinks = new ArrayList<Link>();
    listaLinks.add(new Link("test", "test", "link_afijma"));

    AdaptadorLinks adaplink = new AdaptadorLinks(MainActivity.this, R.layout.linealinks , listaLinks);
    lvLinks.setAdapter(adaplink);

    pager.getAdapter().notifyDataSetChanged();

}

I dont know wheter you need this or not, but here it is anyway:

@Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        toggle.syncState();
    }


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    if (toggle.onOptionsItemSelected(item)) {
        return true;
    }
    int id = item.getItemId();
    if (id == R.id.menuDrawer) {
        drawerLayout.openDrawer(Gravity.START);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Here is my pager adapter (I tried using FragmentStatePagerAdapter too):

public class AdaptadorPager extends FragmentPagerAdapter {

private final String[] titles = { "Presentación", "Noticias", "Links"};

public AdaptadorPager(FragmentManager fragmentManager) {
    super(fragmentManager);
}

@Override
public Fragment getItem(int index) {

    switch (index) {
    case 0:
        return new FragmentoPresentacion();
    case 1:
        return new FragmentoNoticias();
    case 2:
        return new FragmentoLinks();

    }

    return null;
}

@Override
public int getCount() {
    return titles.length;
}

// 3º Poner en el adaptador el método que devuelve la cadena del titulo 
// Devuelve el título segun nos coloquemos en uno u otro fragmento
@Override
public CharSequence getPageTitle(int position) {
    return titles[position];    
}

}

Here is my ListView adapter:

public class AdaptadorLinks extends ArrayAdapter<Link>{

private int             layoutFila;
private LayoutInflater  inflater;
private Context         context;


public AdaptadorLinks(Context ctx, int resourceId, ArrayList<Link> objects) {
    super(ctx, resourceId, objects);
    layoutFila = resourceId;
    inflater = LayoutInflater.from(ctx);
    context=ctx;
}

@Override
public View getView(int position, View fila, ViewGroup parent) {



    fila = inflater.inflate(layoutFila, null );

    Link link = getItem(position);




    ImageView iconfila=(ImageView) fila.findViewById(R.id.imageLineaLinks);
    TextView titulofila = (TextView)fila.findViewById(R.id.tvLineaLinks1);
    TextView urlfila = (TextView)fila.findViewById(R.id.tvLineaLinks2);



    int id=context.getResources().getIdentifier(link.getImagen(), "drawable", context.getPackageName());
    iconfila.setImageResource(id);
    titulofila.setText(link.getTitulo());
    urlfila.setText(link.getUrl());
    return(fila);
}

}

the xmls for the design are:

<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">

<!-- Content -->

<RelativeLayout
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background">

<HorizontalScrollView
    android:id="@+id/horizontalScrollView1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#70000000" >

    <LinearLayout
        android:id="@+id/LinearNoticias"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
    </LinearLayout>
</HorizontalScrollView>

<com.viewpagerindicator.TitlePageIndicator
    android:id="@+id/titulo"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/horizontalScrollView1"
    android:background="#95000000" />

<android.support.v4.view.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/titulo"
    android:background="#80000000" />
</RelativeLayout>

<!-- Navigation Drawer -->

<ListView
    android:id="@+id/lvdrawer"
    android:layout_width="270dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="@color/list_background"/>

</android.support.v4.widget.DrawerLayout>

Fragment for links:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutFragLinks"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<ListView
    android:id="@+id/lvlinksnuevo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true"
    android:background="#90000000" >

</ListView>

</RelativeLayout>

And the line for the LV adapter:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<ImageView
    android:id="@+id/imageLineaLinks"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:src="@drawable/link_emmen" />

<TextView
    android:id="@+id/tvLineaLinks1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_toEndOf="@+id/imageLineaLinks"
    android:layout_toRightOf="@+id/imageLineaLinks"
    android:gravity="center"
    android:text="TextView"
    android:textColor="@color/white"
    android:textSize="15sp" />

<TextView
    android:id="@+id/tvLineaLinks2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/tvLineaLinks1"
    android:layout_alignStart="@+id/tvLineaLinks1"
    android:layout_below="@+id/tvLineaLinks1"
    android:gravity="center"
    android:text="TextView"
    android:textColor="@color/white"
    android:textSize="12sp" />

</RelativeLayout>

Thanks in advance. I hope someone can help me out.

My new fragment code:

public class FragmentoLinks extends Fragment {

private ListView lvLinks;
private ArrayList<Link> listaLinks;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View layout = inflater.inflate(R.layout.frag_links, container, false);

    lvLinks = (ListView)getActivity().findViewById(R.id.lvlinksnuevo);

    listaLinks = new ArrayList<Link>();
    listaLinks.add(new Link("test", "test", "link_afijma"));

    AdaptadorLinks adaplink = new AdaptadorLinks(getActivity(), R.layout.linealinks , listaLinks);
    lvLinks.setAdapter(adaplink);

    return layout;

}
}

I tried getView() instead getActivity() same result.

This is the error i get now:

04-15 12:44:41.192: E/AndroidRuntime(32713): FATAL EXCEPTION: main
04-15 12:44:41.192: E/AndroidRuntime(32713): Process: com.aeioumusica.aplireem, PID: 32713
04-15 12:44:41.192: E/AndroidRuntime(32713): java.lang.NullPointerException
04-15 12:44:41.192: E/AndroidRuntime(32713):    at com.aeioumusica.aplireem.FragmentoLinks.onCreateView(FragmentoLinks.java:32)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.app.Fragment.performCreateView(Fragment.java:1786)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:953)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1136)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1499)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:488)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.view.ViewPager.populate(ViewPager.java:1073)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.support.v4.view.ViewPager$3.run(ViewPager.java:249)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.view.Choreographer.doCallbacks(Choreographer.java:603)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.view.Choreographer.doFrame(Choreographer.java:572)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.os.Handler.handleCallback(Handler.java:733)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.os.Handler.dispatchMessage(Handler.java:95)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.os.Looper.loop(Looper.java:157)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at android.app.ActivityThread.main(ActivityThread.java:5356)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at java.lang.reflect.Method.invokeNative(Native Method)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at java.lang.reflect.Method.invoke(Method.java:515)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
04-15 12:44:41.192: E/AndroidRuntime(32713):    at dalvik.system.NativeStart.main(Native Method)

Upvotes: 0

Views: 179

Answers (3)

krishnan muthiah pillai
krishnan muthiah pillai

Reputation: 2741

Although a Fragment is implemented as an object that's independent from an Activity and can be used inside multiple activities, a given instance of a Fragment is directly tied to the activity that contains it. Specifically, the fragment can access the Activity instance with getActivity() and easily perform tasks such as find a view in the Activity layout:

 View listView = getActivity().findViewById(R.id.list);

Likewise, your Activity can call methods in the Fragment by acquiring a reference to the Fragment from FragmentManager, using findFragmentById() or findFragmentByTag(). For example:

ExampleFragment fragment = (ExampleFragment)
getFragmentManager().findFragmentById(R.id.example_fragment);

Upvotes: 0

dhke
dhke

Reputation: 15388

myContainer = getLayoutInflater().inflate(R.layout.frag_links,null);

This creates a new RelativeLayout with the fragment layout, that is not attached anywhere, is not shown on screen. It certainly does not return the component you want to modify, which is created as part of the fragment.

From your code, you want to modify the ListView inside one of the fragments. That particular fragment, however, may not even be displayed, because ViewPager decides when your fragments get created. The fragment may not yet exist when your code is executed or it may not be on screen.

Most importantly, however, the fragment is not always part of the view hierarchy of your activity. Hence findViewById() on the activity won't find anything since the view may not exist at all.

Move your link update code into the fragment and use layout.findViewById() inside the fragment after inflating the fragment layout. This will attach the ListAdapter to the correct ListView inside the fragment after it is inflated from the layout XML.

Upvotes: 0

MungoRae
MungoRae

Reputation: 1992

In a fragment you should be doing your view setup inside onCreateView(), and then calling

getView().findViewById()

elsewhere.

This is because the lifecycle of a fragment is different from an activity.

See http://developer.android.com/guide/components/fragments.html#Creating for more information.

Upvotes: 1

Related Questions