I am trying to get a LinearLayout to be added to the main Activity view when a button is pressed.
NOTE before trying this with merge I used LinearLayout with the same results. I read this post which made me thing merge would help.
The XML for the View I want to add looks like this.
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/grocery_list_row">
<EditText
android:hint="Price"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:hint="Item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
The java for this View looks like so
package com.example.developer.grocerylist.impl;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import com.example.developer.grocerylist.R;
/**
* Created by developer on 8/16/2015.
*/
public class GroceryListTableRowImpl extends LinearLayout {
int mRows;
public GroceryListTableRowImpl(Context context) {
this(context, null);
}
public GroceryListTableRowImpl(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public GroceryListTableRowImpl(Context context, AttributeSet attributeSet, int defStyles) {
super(context, attributeSet, defStyles);
}
public void addRow(){
mRows++;
removeAllViews();
for(int i = 0; i < mRows; i++){
addView(createRow());
}
}
private View createRow() {
View v;
LayoutInflater inflater = LayoutInflater.from(getContext());
v = inflater.inflate(R.layout.grocery_list_row,this,true);
return v;
}
}
The main Activity's XML looks like this
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".GroceryList"
android:id="#+id/list_table">
<com.example.developer.grocerylist.impl.GroceryListTableRowImpl
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/grocery_list">
</com.example.developer.grocerylist.impl.GroceryListTableRowImpl>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<DigitalClock
android:textSize="20pt"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="250px"
android:textSize="20pt"
android:paddingBottom="5px"
android:text=""
android:background="#777777"
android:textColor="#ff0000" />
<Button
android:id="#+id/add"
android:text="add" />
</TableRow>
</TableLayout>
Finally the main Activity's java
package com.example.developer.grocerylist.activities;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TextView;
import com.example.developer.grocerylist.R;
import com.example.developer.grocerylist.api.GroceryListTableRow;
import com.example.developer.grocerylist.impl.GroceryListTableRowImpl;
public class GroceryList extends AppCompatActivity implements OnClickListener {
TextView textView = null;
GroceryListTableRowImpl groceryListTableRow = null;
Button add = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grocery_list);
textView = (TextView)findViewById(R.id.textview);
groceryListTableRow = (GroceryListTableRowImpl)findViewById(R.id.grocery_list);
add = (Button)findViewById(R.id.add);
add.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_grocery_list, 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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View v) {
groceryListTableRow.addRow();
}
}
When I boot up the App and click the button I get this
Process: com.example.developer.grocerylist, PID: 2353
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3936)
at android.view.ViewGroup.addView(ViewGroup.java:3786)
at android.view.ViewGroup.addView(ViewGroup.java:3727)
at android.view.ViewGroup.addView(ViewGroup.java:3700)
at com.example.developer.grocerylist.impl.GroceryListTableRowImpl.addRow(GroceryListTableRowImpl.java:34)
at com.example.developer.grocerylist.activities.GroceryList.onClick(GroceryList.java:61)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I know this is a lot to take in. I have been scratching my head on this one. I have never made a compound view before. That might be evident. Any help would be greatly appreciated. Thanks in advance!
UPDATE When debugging when I get to the addView(createRow()) line things fail. It does not seem to be making it into the createRow() method.
As per my observation inside your createRow() method change and try this thing
ViewGroup parent = (ViewGroup)v.Parent;
return parent
since you have used merge there is parent viewgroup, so either return parent view or remove the parent using
parent.RemoveView(v);
return v;
Thanks to #njkz2
What fixed this for me was changing my onCreate() method to this.
private View createRow() {
View v;
LayoutInflater inflater = LayoutInflater.from(getContext());
v = inflater.inflate(R.layout.grocery_list_row,this,false);
return v;
}
Also I changed the class to extend TableLayout instead of LinearLayout to get the desired effect. This is because I was added the compound view (which is a LinearLayout) to my GroceryListTableRowImpl. So GroceryListTableRowImpl needed to be a TableLayout.
Related
Hey guys I am a beginner in Android Develpoment. I am currently learning Navigation Components, but stuck in this app. I am setting listener to the button present in the activity_main.xml inside the FirstFragment.java and SecondFragment.java but my app crashes. I don't know what I am doing wrong.
Main Activity.java
package com.ahstore.inventory;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.ahstore.inventory.databinding.ActivityMainBinding;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration appBarConfiguration;
private ActivityMainBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
binding.fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:theme="#style/Theme.Inventory.AppBarOverlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="#style/Theme.Inventory.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<HorizontalScrollView
android:id="#+id/horizontalScrollView"
android:layout_width="409dp"
android:layout_height="50dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:scrollIndicators="none"
android:scrollbarAlwaysDrawHorizontalTrack="false"
android:scrollbarAlwaysDrawVerticalTrack="false"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:text="Button" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:text="Button" />
</LinearLayout>
</HorizontalScrollView>
<fragment
android:id="#+id/nav_host_fragment_content_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/horizontalScrollView"
app:navGraph="#navigation/nav_graph" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="#android:drawable/ic_input_add"
tools:ignore="SpeakableTextPresentCheck,SpeakableTextPresentCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>
FirstFragment.java
package com.ahstore.inventory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.ahstore.inventory.databinding.FragmentFirstBinding;
public class FirstFragment extends Fragment {
private FragmentFirstBinding binding;
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
View view=inflater.inflate(R.layout.fragment_first,container,false);
return view;
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button button1=view.findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
fragment_first.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".FirstFragment">
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="First" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
SecondFragment.java
package com.ahstore.inventory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.ahstore.inventory.databinding.FragmentSecondBinding;
public class SecondFragment extends Fragment {
private FragmentSecondBinding binding;
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
View view=inflater.inflate(R.layout.fragment_second,container,false);
return view;
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button button=view.findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}
});
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
fragment_second.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="#+id/cl"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondFragment">
<TextView
android:id="#+id/textview_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="am second"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Error
2022-03-04 16:54:11.473 2392-2392/com.ahstore.inventory E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ahstore.inventory, PID: 2392
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ahstore.inventory/com.ahstore.inventory.MainActivity}: android.view.InflateException: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3800)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3976)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2315)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8550)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: android.view.InflateException: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Error inflating class fragment
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.ahstore.inventory.FirstFragment.onViewCreated(FirstFragment.java:35)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:392)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:140)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:319)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:298)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at com.ahstore.inventory.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:75)
at com.ahstore.inventory.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:69)
at com.ahstore.inventory.MainActivity.onCreate(MainActivity.java:32)
at android.app.Activity.performCreate(Activity.java:8198)
2022-03-04 16:54:11.474 2392-2392/com.ahstore.inventory E/AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8182)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3773)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3976)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2315)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8550)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Here are a few points that will help you understand your issue better
Your activity and fragments have their own respective layout files (xmls)
View are bound within their layout files. Simply put, if an element with id, say A, is present in activity_main.xml, then it can only be accessed when the layout being inflated is activity_main.xml. If the contentView of your Activity is activity_main.xml, it will be able to access all Views inside the layout file.
In fragments, the layout is inflated in the onCreateView method, which returns the resulting View for the Fragment. The findViewById(id) method is called against that View object. The method will look for the View with the given id inside that View only. If it is able to find the View it will return it, else it will return null. Same goes for finding a View inside an Activity (you do not need to specify the View for an Activity as it will automatically reference the layout that is specified in setContentView).
Now that we have the above points cleared, we can see the issue that you are facing. Firstly, the buttons with ids button1 and button2 are in your activity_main.xml layout file. However you are trying to access these from your Fragment1 and Fragment2 classes. But your Fragment1 and Fragment2 classes have their own layout files which do not have the two buttons. So, when you try to retrieve the buttons (using findViewById), it returns null because the buttons are not present in the layout. You then try to set a click listener. Since, the button object is null, calling any method on it will result in a Null Pointer Exception being throw.
We now understand what you are doing wrong. Now, how do we fix this. First you need to understand what it is you want to achieve. In this case I would suggest that you move both buttons to the respective Fragment layouts i.e. the View with id button1 will go to Fragment1 and the View with id button2 will go to Fragment2. This should help resolve the NPE that you are facing.
Still there are some cases where a Fragment might want to access a View that is present in its parent Activity. One of the ways to do this would be to
Create a public method in your Activity class which returns a View with the given id.
public View getViewById(int id) {
return findViewById(id);
}
Use this method in your Fragment by doing so
((MainActivity) getActivity()).getViewById(R.id.button1)
Other approaches involve using Interfaces which I am sure you will learn about as you continue learning more.
Just to wrap things up, you have two ways to go about fixing your issue. Either move the buttons to the fragment layout files or create a public method to retrieve those views.
I'm working on a course list app which loads each course title together with the course image in a listview through ArrayAdapter, I want to implement asynctask for loading of images in between listview and ArrayAdapter because the listview is lagging while scrolling, Please Help me.
MainActivity.java
package com.emmakade.okt;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity {
protected List<Course> data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
data = DataProvider.getData();
ArrayAdapter<Course> courseArrayAdapter =
new CourseArrayAdapter(this, 0, data);
ListView listView = (ListView) findViewById(android.R.id.list);
listView.setAdapter(courseArrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Course course = data.get(position);
displayDetail(course);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DETAIL_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
String msg = data.getStringExtra("resultMessage");
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
}
}
class CourseArrayAdapter extends ArrayAdapter<Course>{
Context context;
List<Course> objects;
public CourseArrayAdapter(Context context, int resource, List<Course> objects) {
super(context, resource, objects);
this.context = context;
this.objects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Course course = objects.get(position);
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.course_item, null);
TextView tv = (TextView) view.findViewById(R.id.tvTitle);
tv.setText(course.getTitle());
ImageView iv = (ImageView) view.findViewById(R.id.imageCourse);
int res = context.getResources().getIdentifier(
"image_" + course.getCourseNumber(), "drawable",
context.getPackageName()
);
iv.setImageResource(res);
return view;
}
}
}
activity_main.xml
<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=".MainActivity">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="#+id/imageLogo"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:src="#drawable/academy"/>
<TextView
android:id="#+id/txtOutput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/course_catalog"
android:layout_alignBottom="#+id/imageLogo"
android:layout_toEndOf="#+id/imageLogo"
android:layout_marginStart="20dp"
android:layout_marginBottom="15dp"
android:textSize="28sp" />
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#android:id/list"
android:layout_below="#+id/imageLogo"
android:layout_marginTop="10dp"
android:layout_alignParentStart="true" />
</RelativeLayout>
course_item.xml
<?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"
android:padding="10dp">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:id="#+id/imageCourse" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvTitle"
android:layout_toEndOf="#+id/imageCourse"
android:layout_marginStart="10dp"
android:textSize="18sp"/>
</RelativeLayout>
enter image description here
I recommend you to use Glide library for asynchronous image loading, caching and displaying.
Add Dependency
implementation 'com.github.bumptech.glide:glide:4.5.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'
Use like this in adapter
Glide.with(this).load("url").into(imageView);
ImageView iv = (ImageView) view.findViewById(R.id.imageCourse);
int res = context.getResources().getIdentifier(
"image_" + course.getCourseNumber(), "drawable",
context.getPackageName()
);
Glide.with(this).load(res).into(iv);
You can use handler because asynctask will work on another thread but you cant update ui from another thread instead of main thread. Also consider to use glide, picasso like libraries. These libraries caches images efficiently and works with more performence.
There is an example with Handler.
Handler handler = new Handler();
handler.post(() -> {
profilephoto.setImageBitmap(pp);
});
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I tried creating a simple app "MemeCrater" which i learned from one of youtube tutorial.but whenever i press the Create button.The App crashes.
This is the error i get.
Error
Process: com.example.iemshekhar.memegenerator, PID: 13118
java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.iemshekhar.memegenerator.TopSectionFragment$TopSectionListener.createMeme(java.lang.String, java.lang.String)' on a null object reference
at com.example.iemshekhar.memegenerator.TopSectionFragment.buttonClicked(TopSectionFragment.java:57)
at com.example.iemshekhar.memegenerator.TopSectionFragment$1.onClick(TopSectionFragment.java:49)
at android.view.View.performClick(View.java:5697)
at android.widget.TextView.performClick(TextView.java:10815)
at android.view.View$PerformClick.run(View.java:22526)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
This is my main activity java file:
MainActivity.java
package com.example.iemshekhar.memegenerator;
import android.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity implements TopSectionFragment.TopSectionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void createMeme(String top, String bottom) {
BottomPictureFragment bottmfragment=(BottomPictureFragment)getFragmentManager().findFragmentById(R.id.fragment2);
bottmfragment.setMemeText(top,bottom);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
This is my top Fragement java file:
TopSectionFragment.java
package com.example.iemshekhar.memegenerator;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class TopSectionFragment extends Fragment {
private static EditText top, bottom;
TopSectionListener activitycommander;
public interface TopSectionListener{
public void createMeme(String top,String bottom);
}
public void onAtttach(Context context)
{
try{
activitycommander=(TopSectionListener)context;
}
catch(ClassCastException e){
throw new ClassCastException(e.getMessage());
}
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.top_section_fragment, container, false);
top = (EditText)view.findViewById(R.id.toptextinput);
bottom = (EditText) view.findViewById(R.id.bottomtextinput);
final Button create = (Button) view.findViewById(R.id.createbutton);
create.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
buttonClicked(v);
}
}
);
return view;
}
public void buttonClicked(View v) {
activitycommander.createMeme(top.getText().toString(),bottom.getText().toString());
}
}
This file is my bottom Fragment java File:
BottomSectionFragment.java
package com.example.iemshekhar.memegenerator;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* Created by IEmShekhar on 6/18/2016.
*/
public class BottomPictureFragment extends Fragment {
public static TextView toptext,bottomtext;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_picture_fragment, container, false);
toptext=(TextView)view.findViewById(R.id.textView1);
bottomtext=(TextView)view.findViewById(R.id.textView2);
return view;
}
public void setMemeText(String top,String bottom){
toptext.setText(top);
bottomtext.setText(bottom);
}
}
These are my XML Files:
activity_main.xml
<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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:background="#006669"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<fragment
android:layout_width="wrap_content"
android:layout_height="290dp"
android:name="com.example.iemshekhar.memegenerator.BottomPictureFragment"
android:id="#+id/fragment2"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
tools:layout="#layout/bottom_picture_fragment" />
<fragment
android:layout_width="400dp"
android:layout_height="wrap_content"
android:name="com.example.iemshekhar.memegenerator.TopSectionFragment"
android:id="#+id/fragment"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
tools:layout="#layout/top_section_fragment"
android:layout_above="#+id/fragment2" />
</RelativeLayout>
Top_section_Fragment.xml
<?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" android:background="#999999">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/toptextinput"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:width="300dp"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/bottomtextinput"
android:layout_centerHorizontal="true"
android:layout_below="#+id/toptextinput"
android:width="300dp"
android:layout_marginTop="30dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="150dp"
android:layout_centerHorizontal="true"
android:text="#string/Create_text"
android:background="#006666"
android:textStyle="bold"
android:id="#+id/createbutton"/>
</RelativeLayout>
Bottom_picture_Fragement.xml
<?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"
android:background="#drawable/afaque">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/toptext"
android:textStyle="bold"
android:textSize="25sp"
android:background="#ffff"
android:width="400dp"
android:textAlignment="center"
android:id="#+id/textView1"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/bottomtext"
android:textStyle="bold"
android:textSize="25sp"
android:background="#ffff"
android:width="400dp"
android:textAlignment="center"
android:id="#+id/textView2"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
Guessing that you're trying to set the text from editText, You should be accessing the text from your editText in your TopSectionFragment
Replace
//Initialize
`private static TextView top, bottom;`
//onCreateView() Method
top = (TextView) view.findViewById(R.id.textView1);
bottom = (TextView) view.findViewById(R.id.textView2);
with this
//Initialize
`private static EditText top, bottom;`
//onCreateView Method
//onCreateView() Method
top = (EditText) view.findViewById(R.id.toptextinput);
bottom = (EditText) view.findViewById(R.id.bottomtextinput);
in your TopSectionFragment. Hope this will help :)
I'm having some issues with my school project. I can't get the text from the textbox. I searched for a solution but nothing found.. I'll be grateful if somebody help me :)
So here is my Java code:
package com.src.vicnote;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.os.Build;
public class NewNoteActivity extends ActionBarActivity {
Button saveButton;
EditText textData;
Context context;
String text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_note);
saveButton = (Button) this.findViewById(R.id.buttonSave);
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
textData = (EditText) findViewById(R.id.editText);
text = textData.getText().toString();
//text = "this is sparta!";
Log.d("ADebugTag", "string: \"" + text + "\" end of note text");
new SaveClass(text/*, context.getApplicationContext()*/);
}
});
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.new_note, 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.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new_note,
container, false);
return rootView;
}
}
}
And my XML
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.src.vicnote.NewNoteActivity"
tools:ignore="MergeRootFrame" >
<Button
android:id="#+id/buttonSave"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Save" />
<EditText
android:id="#+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="#+id/buttonSave"
android:ems="10"
android:gravity="top"
android:inputType="textMultiLine" >
<requestFocus />
</EditText>
</RelativeLayout>
Also I want to ask you what will happen if the text is cyrillic? Will be there any problem?
Can't really tell what your error is without a logCat.
but one thing that might fix your problem is replacing
textData = (EditText) findViewById(R.id.editText);
text = textData.getText().toString();
with
textData = (EditText)getActivity().findViewById(R.id.editText);
text = textData.getText().toString();
// Toast for debugging purposes
Toast.makeText(getActivity(),text,0).show();
When using Fragments you should really read about getView() & getActivity().
Update
where in the xml have you set the text?
you need to set your text to something before you actually call the getText() command.
<EditText
android:id="#+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="#+id/buttonSave"
android:ems="10"
android:gravity="top"
----- add this line ------
android:text="whatever you want"
--------------------------
android:inputType="textMultiLine" >
Good Luck
Adding a getActivity() did the trick before accessing the editText.
For example:
EditText addressText = (EditText) getActivity().findViewById(R.id.location);
getEditableText return an editable object, and you can't edit the object like that, so it is null.
simply use "getText" instead.
I don't know about Cyrillic, but it shouldn't cause any problems.
[EDIT]: Thank you for all the meaningful answers, the problem is now solved, thank to your help. Similar issue: Android: I am unable to have ViewPager WRAP_CONTENT
I'm trying to implement the UI of my app : I want a ListView with a ViewPager in each row.
Here are my files :
MainActivity.java
package com.condi;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.Menu;
public class MainActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setListAdapter(new CardListAdapter(this, getFragmentManager()));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
CardListAdapter.java
package com.condi;
import java.util.List;
import android.app.FragmentManager;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
public class CardListAdapter extends BaseAdapter {
private Context context;
private FragmentManager fragmentManager;
private List<Profile> profiles;
CardListAdapter(Context context, FragmentManager fragmentManager) {
this.context = context;
this.fragmentManager = fragmentManager;
this.profiles = new DatabaseHelper(context).getProfiles();
}
#Override
public int getCount() {
return profiles.size();
}
#Override
public Profile getItem(int position) {
return profiles.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = View.inflate(context, R.layout.profile_card, null);
CardPagerAdapter mCardPagerAdapter = new CardPagerAdapter(
fragmentManager);
ViewPager viewPager = (ViewPager) convertView.findViewById(R.id.pager);
viewPager.setAdapter(mCardPagerAdapter);
viewPager.setId(R.id.pager);
return convertView;
}
}
profile_card.xml (issue came from wrap_content).
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="4dp"
android:background="#drawable/card_background"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</FrameLayout>
CardPagerAdapter.java
package com.condi;
import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v13.app.FragmentPagerAdapter;
public class CardPagerAdapter extends FragmentPagerAdapter {
public CardPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
}
return null;
}
#Override
public int getCount() {
return 2;
}
}
Fragment1.java
package com.condi;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment1 extends Fragment {
public Fragment1() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.preference_category, container, false);
}
}
Fragment2.java
package com.condi;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment2 extends Fragment {
public Fragment2() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.preference_category, container, false);
}
}
The database that furnishes the profiles is working well.
The problem is that I am getting an empty list with the correct number of item, but no ViewPager displayed at all. screenshot of my app
What am I doing wrong ?
Try to change your ViewPager's height in xml. wrap_content does not work.
To make is clear, its a bad practice to use viewpagers inside a list view as this design hits the ui performance. The best way to handle this problem is:
To do manual inflation of viewpagers and add to a layout.
Add a unique id to each viewpager so that it is identified uniquely by the system.
Extend a custom viewpager and onmeasure() measure the child layout inflated at the page selected. You can do this by setting a callback in your custom viewpager and trigger the callback from viewpagers onPageScrolled listener, passing the position to identify the child layout.
In your onMeaure() method measure the child layout height and set it as the viewpagers height using super.onMeasure() passing the newly measured specs.
Key points to make a note of :
N.B. Set a unique id to the viewpager inflated by you.
try this problem in layout height
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="4dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="4dp"
android:background="#drawable/card_background"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</FrameLayout>
It's a bad practice to use wrap_content for your viewpager's height. You can use match_parent or a static dp for your viewpager's height.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="4dp"
android:background="#drawable/card_background"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</FrameLayout>
If it's a must to use wrap_content for your viewpager's height you can override your viewpager's onMeasure() and calculate height. Here's an example below about it.
Android: I am unable to have ViewPager WRAP_CONTENT
I hope this'll help you.
ViewPager doesn’t support wrap_content as it stands now because it doesn’t load all of its children at the same time, meaning it can’t get an appropriate measurement. You must fix View's height in your xml or create a custom ViewPager (read more at here) and use it in your xml
Try using a fixed height ViewPager inside the ListView.ViewPager does not support wrap_content