I'm getting a very odd (to me) issue when populating a GridView - when it first loads all looks fine, but scrolling ends up with data from cells moving to other positions. In the following example I just have an ArrayList of the numbers 0-800, and an 8 column grid. When loaded 0-7 is in the first row, 8-15 in the second etc, with a different value in the first cell in each row. But after scrolling the first column value will change. Here's the code - it's driving me crazy!
MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<Integer> positions = new ArrayList<Integer>();
for(int i=0;i<800;i++) {
positions.add(i);
}
GridView gvVals = findViewById(R.id.gvVals);
CellAdapter adapter = new CellAdapter(this, new ArrayList<Integer>());
adapter = new CellAdapter(this, positions);
gvVals.setAdapter(adapter);
}
Cell Adapter.java:
public class CellAdapter extends ArrayAdapter<Integer> {
private Context context;
public CellAdapter(Context context, ArrayList<Integer> vals) {
super(context, 0, vals);
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
v = LayoutInflater.from(getContext()).inflate(R.layout.activity_cell, parent, false);
} else {
v = (View)convertView;
}
TextView tvDay = v.findViewById(R.id.tvVal);
tvDay.setVisibility(View.VISIBLE);
if(position % 8 == 0) {
tvDay.setText("ST:"+position);
}
else
{
v.findViewById(R.id.btnM).setVisibility(View.VISIBLE);
((Button)v.findViewById(R.id.btnM)).setText(position + " ");
tvDay.setText(" ");
}
return v;
}
ActivityMain.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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=".MainActivity">
<GridView
android:id="#+id/gvVals"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="60dp"
android:numColumns="8"/>
</android.support.constraint.ConstraintLayout>
ActivityCell.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tvVal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:visibility="invisible"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="#+id/btnM"
android:layout_width="0dp"
android:layout_weight=".34"
android:layout_height="20dp"
android:text="M"
android:background="#color/colorAccent"
android:minWidth="0dp"
android:visibility="invisible"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
GridView when app first opened
After scrolling down a few rows and then back up
Change this:
TextView tvDay = v.findViewById(R.id.tvVal);
tvDay.setVisibility(View.VISIBLE);
if(position % 8 == 0) {
tvDay.setText("ST:"+position);
}
else
{
v.findViewById(R.id.btnM).setVisibility(View.VISIBLE);
((Button)v.findViewById(R.id.btnM)).setText(position + " ");
tvDay.setText(" ");
}
to this:
boolean firstColumn = position % 8 == 0;
TextView tvDay = v.findViewById(R.id.tvVal);
tvDay.setVisibility(firstColumn ? View.VISIBLE : View.GONE);
Button btnM = v.findViewById(R.id.btnM);
btnM.setVisibility(firstColumn ? View.GONE : View.VISIBLE);
if(firstColumn) {
tvDay.setText("ST:"+position);
}
else
{
btnM.setText(position + " ");
}
It's important when working with RecyclerView to make sure that you always update every view every time. This is because old view holders get recycled, so if you only do something some of the time, it can get overwritten or it can overwrite the "expected" behavior.
Previously, you were making btnM visible if it wasn't the first column, but you weren't making it not visible if it was the first column.
Related
I am working on a WearOS app. I am using a ListView to show a list of strings. Right now, the ListView looks like this:
I want a single row to take up the entire screen. Once a user swipes up, then Row 2 takes up the entire screen. Swipe up again and Row 3 takes up the entire screen, etc. So like this:
I came across this link, which is exactly what I want to do, but the first method doesn't work and the second method suggests a library, but I don't want to use a library for what seems like a pretty simple task. I don't want to use RecyclerView. Thank you for your help.
Here is my XML file for the main activity, which is where the ListView is.
<?xml version="1.0" encoding="utf-8"?>
<android.support.wear.widget.BoxInsetLayout 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"
android:background="#color/dark_grey"
android:padding="#dimen/box_inset_layout_padding"
tools:context=".MainActivity"
tools:deviceIds="wear">
<!-- Change FrameLayout to a RelativeLayour -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/inner_frame_layout_padding"
app:boxedEdges="all">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
</android.support.wear.widget.BoxInsetLayout>
Try the following (The idea here is to programmatically set the height of the textView to the height of the screen):
1) MnnnnnnnActivity.class:----------
public class MnnnnnnnActivity extends AppCompatActivity {
private ListView lv;
private CustomAdapter customAdapter;
private String[] s = new String[10];
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout6);
for (int i = 0; i < 10; i++) {
s[i] = "ROW " + String.valueOf(i + 1);
}
lv = (ListView) findViewById(R.id.lv);
customAdapter = new CustomAdapter(MnnnnnnnActivity.this, s);
lv.setAdapter(customAdapter);
}
public int getScreenHeight() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
}
2) CustomAdapter.class:--------
public class CustomAdapter extends ArrayAdapter<String> {
private String[] s;
private WeakReference<MnnnnnnnActivity> mActivity;
public CustomAdapter(MnnnnnnnActivity activity1, String[] s) {
super(activity1.getApplicationContext(), R.layout.list_view_item, s);
this.s = s;
mActivity = new WeakReference<MnnnnnnnActivity>(activity1);
}
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(mActivity != null) {
MnnnnnnnActivity activity = mActivity.get();
if (activity != null) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(activity);
convertView = inflater.inflate(R.layout.list_view_item, null);
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.tv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(s[position]);
holder.tv.setHeight(activity.getScreenHeight());
}
}
return convertView;
}
private class ViewHolder {
TextView tv;
}
}
3) layout6.xml:-----------
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lv">
</ListView>
</android.support.constraint.ConstraintLayout>
4) list_view_item.xml:----------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="-"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold">
</TextView>
</LinearLayout>
5) Note: Although this is tested on phone, the same idea can be used to achieve something similar on a wareable. Also, a better approach would be to set the height of the linearLayout (which contains the textView) to the screen height.
6) Output:
I have an Activity that contains a Fragment. Fragment contains a RecyclerView, displaying CardViews.
CardView is very simple, just a TextView and a CustomView. This is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="#+id/card_current_heat_cardview"
android:layout_gravity="center_vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:weightSum="4">
<TextView
android:id="#+id/card_current_heat_textview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textStyle="bold"
android:textColor="#000000"
android:background="#android:color/holo_red_dark"
android:gravity="center_vertical"/>
<com.amige.vm2.CurrentHeatChartView
android:id="#+id/card_current_heat_chart_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
TextView should use 1/4 of the width, and the CustomView 3/4.
Im having trouble understanding why weights are ignored the first time the RecyclerView loads
Image of RecyclerView loaded for the first time
But if I scroll up and down, the layout works as expected for some Cards
Image of RecyclerView scrolled up and down
I also have another Activity (no fragment involved here) that has a RecyclerView and IS using this same CardView Layout and it works perfectly!!
I dont know if it has to do with the Fragment...
What am I missing?
Thanks!
EDIT
This the Adapter code
public class MainAdapter extends RecyclerView.Adapter<MyFragment.MainAdapter.ViewHolder>
{
public MainAdapter()
{
}
#Override
public MyFragment.MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_current_heat, parent, false);
return new MyFragment.MainAdapter.ViewHolder(v);
}
#Override
public void onBindViewHolder(MyFragment.MainAdapter.ViewHolder holder, int position)
{
if (arrayList.size() == 2)
{
if (position == 0)
{
holder.variableNameTextView.setText(“Var Name”);
holder.currentHeatChartView.reloadChartWithSamples(arrayList.get(0));
}
else
{
if ((position - 1) < arrayList.get(1).size())
{
HashMap variableHashMap = (HashMap) arrayList.get(1).get(position - 1);
holder.variableNameTextView.setText(variableHashMap.get("VarName") != null ? (String)variableHashMap.get("VarName") : "");
holder.currentHeatChartView.reloadChartWithVariableValuesAndColors(variableHashMap, colorGradientsArrayList.get((position - 1) % colorGradientsArrayList.size()));
}
}
}
}
#Override
public int getItemCount()
{
if (arrayList.size() == 2)
{
if (arrayList.get(1).size() > 0)
{
return 1 + arrayList.get(1).size();
}
else
{
return 1;
}
}
return 0;
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView variableNameTextView;
CurrentHeatChartView currentHeatChartView;
public ViewHolder(View v)
{
super(v);
this.variableNameTextView = (TextView) v.findViewById(R.id.card_current_heat_textview);
this.currentHeatChartView = (CurrentHeatChartView) v.findViewById(R.id.card_current_heat_chart_view);
}
}
}
I found the culprit.
There was a ConstraintLayout on top of the hierarchy of the Activity containing the Fragment. Since I was working with nested layouts, ConstraintLayout was not the right way to go.
I changed it to RelativeLayout and the cards are now rendered properly.
I think your layout inflation is wrong.
View view = View.inflate(mContext, R.layout.your_layout, null);
If you do like that change your code like this.
View view = LayoutInflater.from(mContext).(R.layout.your_layout, parent, false);
Hope it helps:)
My goal is to display a chessboard. I have an Activity which displays a menu and load an instance of "ChessView" which extends GridView. I've created a custom GridView because I want to have a class fully dedicated to its display. So that class have its own layout.xml etc ...
GameActivity.java :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
//init a game
CChess.getInstance().init();
//creating the chessboard
ChessView lChessView = (ChessView) findViewById(R.id.chessView);
}
activity_game.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:background="#color/background"
tools:context=".GameActivity" >
<project.chess.view.ChessView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ChessView" >
</project.chess.view.ChessView>
</RelativeLayout>
ChessView.java :
public class ChessView extends GridView {
public ChessView(Context pContext, AttributeSet pAttrs) {
super(pContext, pAttrs);
GridView.inflate(pContext, R.layout.view_chess, null);
this.setAdapter(new ChessAdapter(pContext));
}
}
view_chess.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<GridView
android:id="#+id/gridView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:numColumns="8"
android:gravity="center"
>
</GridView>
</LinearLayout>
ChessAdapter.java :
public class ChessAdapter extends BaseAdapter
{
private Context mContext;
public ChessAdapter (Context pContext)
{
this.mContext = pContext;
}
#Override
public int getCount()
{
return 64;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView lImageView;
if (convertView == null) {
lImageView = new ImageView(mContext);
int size = parent.getWidth()/8;
lImageView.setLayoutParams(new GridView.LayoutParams(size,size));
//background black or white depending of the position
int col = position/8 %2;
if (col == 0)
{
if (position%2 == 0)
lImageView.setBackgroundColor(Color.WHITE);
else
lImageView.setBackgroundColor(Color.BLACK);
}
else
{
if (position%2 == 0)
lImageView.setBackgroundColor(Color.BLACK);
else
lImageView.setBackgroundColor(Color.WHITE);
}
//load images
CPiece p = CChess.getInstance().getPiece(position/8, position%8);
if( p != null)
lImageView.setImageResource(mContext.getResources().getIdentifier(p.toString(), "drawable", mContext.getPackageName()));
} else {
lImageView = (ImageView) convertView;
}
return lImageView;
}
}
The result is : i have just 1 column of 64 squares all with an image (my init() in CChess is ok). To be clear, i want a 8x8 grid like all standards chessboards.
Few days ago, i had all this stuff in one activity without my custom view but just a simple gridView and all was working correctly. I have broken it since i've decided to separate my code in different classes
I'm sure i forgot something like an inflater somewhere but i don't understand how it works and what it does. I've parsed google for hours but i couldn't find the answer.
Can you help me please ? Thanks a lot for reading me and sorry for my english
I Think the problem with this LayoutInflator in ChessView.java
remove this line from that class
No Need to Inflate the GridView in that class
GridView.inflate(pContext, R.layout.view_chess, null);
and set the Column count and gravity in Chess View in activity_game.xml file.
android:layout_width="wrap_content"
android:numColumns="8"
I Think this works for you.
I have a Activity that displays a list of check boxes (Focus Areas) that can be assigned to an activity event in my application. However I want to be able to prevent the user form editing these values until a button is clicked to put the form into edit mode.
Can some one explain or provide code sample how I can implement this into my application?
This list is held in a ListView with a custom ArrayAdapter of a Type FocusArea a class I have created for my application.
The xml for the Activity is shown below:
<?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/horizontal_gradient_line_reverse">
<TextView
android:id="#+id/textViewCustomerNameNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Customer Name & Number" android:layout_margin="5dp"/>
<ListView
android:id="#+id/listViewFocusAreas"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/relativeLayoutControls"
android:layout_alignParentLeft="true"
android:layout_below="#+id/textViewCustomerNameNumber"
android:layout_margin="5dp"
android:background="#drawable/myborder" >
</ListView>
<RelativeLayout
android:id="#+id/relativeLayoutControls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" >
<ImageView
android:id="#+id/imageViewCancelFocusAreaChanges"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_mini_undo" />
<ImageView
android:id="#+id/imageViewSaveFocusAreaChanges"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/imageViewCancelFocusAreaChanges"
android:src="#drawable/ic_mini_save" />
<ImageView
android:id="#+id/imageViewEditFocusArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/imageViewSaveFocusAreaChanges"
android:src="#drawable/ic_mini_edit" />
</RelativeLayout>
<ImageView
android:id="#+id/imageViewEditMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/textViewCustomerNameNumber"
android:layout_alignRight="#+id/listViewFocusAreas"
android:src="#drawable/edit16x16"
android:visibility="gone" />
</RelativeLayout>
The following is the xml for the focus area row:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<CheckBox
android:id="#+id/checkBoxFocusArea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Focus Area" />
</LinearLayout>
The following is the code for the Custom ArrayAdapter:
public class FocusAreaAdapter extends ArrayAdapter<FocusArea> {
private ArrayList<FocusArea> focusAreas;
private Context context;
public FocusAreaAdapter(Context context, int textViewResourceId, ArrayList<FocusArea> focusAreas) {
super(context, textViewResourceId, focusAreas);
this.context = context;
this.focusAreas = focusAreas;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View v = convertView;
if(v == null) {
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.focus_area_menu_item, null);
}
FocusArea focusArea = focusAreas.get(position);
if(focusArea != null) {
CheckBox cbFocusArea = (CheckBox)v.findViewById(R.id.checkBoxFocusArea);
cbFocusArea.setText(focusArea.getFocusAreaCodeDescription());
if(focusArea.isFocusAreaCodeChecked() == 1) {
cbFocusArea.setChecked(true);
} else {
cbFocusArea.setChecked(false);
}
cbFocusArea.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FocusArea focusArea = focusAreas.get(position);
if(focusArea.isFocusAreaCodeChecked() == 1) {
focusArea.setFocusAreaCodeChecked(0);
} else {
focusArea.setFocusAreaCodeChecked(1);
}
}
});
}
return v;
}
}
Finally I instanciate my custom array adapter with the following code:
private void assignFocusAreasToAdapter() {
// get reference to available responsibles list view control
lvFocusAreas.clearChoices();
// create an array adapter with the communications data array
activityFocusAreaAdapter = new FocusAreaAdapter(this, R.layout.focus_area_menu_item, activityFocusAreas);
// assign the my customers list control the array adapter
lvFocusAreas.setAdapter(activityFocusAreaAdapter);
activityFocusAreaAdapter.notifyDataSetChanged();
Log.i(TAG, "Available Activity Focus Areas Loaded");
}
Ok i found the solution to this problem for anyone who might have the same issue.
The XML for the Focus Area activity stays the same as posted above.
The XML for the Focus Area row item is modified accordingly:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:descendantFocusability="blocksDescendants" >
<CheckBox
android:id="#+id/checkBoxFocusArea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Focus Area" />
</LinearLayout>
You can see that this now has the following line added android:descendantFocusability="blocksDescendants" This prevents the checkboxes onClickListener from firing which normally will block the ListViews OnItemClickedListener from firing.
The Custom Adapter code is modified to remove the checkboxes OnClickListener like so:
public class FocusAreaAdapter extends ArrayAdapter<FocusArea> {
private ArrayList<FocusArea> focusAreas;
private Context context;
public FocusAreaAdapter(Context context, int textViewResourceId, ArrayList<FocusArea> focusAreas) {
super(context, textViewResourceId, focusAreas);
this.context = context;
this.focusAreas = focusAreas;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View v = convertView;
if(v == null) {
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.focus_area_menu_item, null);
}
FocusArea focusArea = focusAreas.get(position);
if(focusArea != null) {
CheckBox cbFocusArea = (CheckBox)v.findViewById(R.id.checkBoxFocusArea);
cbFocusArea.setText(focusArea.getFocusAreaCodeDescription());
if(focusArea.isFocusAreaCodeChecked() == 1) {
cbFocusArea.setChecked(true);
} else {
cbFocusArea.setChecked(false);
}
cbFocusArea.setClickable(false);
}
return v;
}
}
The Custom Adapter is instanciated using the same code as posted in above but you must add an OnItemClickListener to the ListView and preform the check of the checkbox inside the OnItemClickListener click event like so:
lvFocusAreas = (ListView)findViewById(R.id.listViewFocusAreas);
lvFocusAreas.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
if(editMode){
FocusArea focusArea = (FocusArea)lvFocusAreas.getItemAtPosition(position);
if(focusArea.isFocusAreaCodeChecked() == 0) {
focusArea.setFocusAreaCodeChecked(1);
} else {
focusArea.setFocusAreaCodeChecked(0);
}
activityFocusAreaAdapter.notifyDataSetChanged();
setControlsEnabled();
}
}
});
Hope this helps any one thats having the same problem. :D
i have a list in android. and it has 30 records currently.
but on my activity i am only showing 5 records... after 5 records it shows me a button
"Display All Data"
when i click on that button, then it should display all 30 records and update the activity List. Please tell me how can i update. like we do in AJAX in web technology. i hope u guys understand what i am trying to say?
Refresh the Activity without refreshing the whole activity. Please Reply Friends.
waiting for positive response.
You should just simply add the newly arrived items to your list of data (the already listed 5 items), and call notifyDatasetChanged() on your ListAdapter implementation.
Update
Here I share a sample activity which contains a list and a TextView at the bottom (inflated from stepping_list.xml), where the list initially contains 5 items, and at the bottom a button. When pressing the button, other 25 values get loaded into the list, and the button disappears.
For this we need the main layout, res/layout/stepping_list.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:id="#+id/footer"
android:layout_width="fill_parent" android:layout_height="60dp"
android:background="#drawable/box"
android:text="Lazy loading list in steps" android:textStyle="bold"
android:gravity="center_vertical|center_horizontal"
android:layout_alignParentBottom="true" />
<ListView android:id="#+id/list"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_alignParentTop="true" android:layout_above="#id/footer" />
</RelativeLayout>
For the Load more data button to always appear after the last item of the initial list (even if need to scroll to it), I put it into the list's item renderer layout. This way the list will have two item renderers.
The common renderer res/layout/row.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/textView" android:layout_alignParentRight="true"
android:layout_width="fill_parent" android:layout_height="60dp"
android:gravity="center_vertical|right" android:paddingRight="10dp"
android:textSize="35dp"
android:textColor="#2B78E4" />
is a simple TextView, and the renderer for the last item (of the initial list)
res/layout/row_with_button.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">
<TextView android:id="#+id/textView"
android:layout_alignParentRight="true"
android:layout_width="fill_parent" android:layout_height="60dp"
android:gravity="center_vertical|right" android:paddingRight="10dp"
android:layout_weight="1" android:textColor="#2B78E4"
android:textSize="35dp" />
<Button android:id="#+id/loadbtn"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="1" android:text="Load more data"
android:onClick="loadMoreData" />
</LinearLayout>
Finally the Activity class that connects these layouts:
SteppingListActivity.java:
public class SteppingListActivity extends Activity
{
private MyAdapter adapter;
private ArrayList<Integer> values;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.stepping_list);
//initialize the list of data which will populate the list
//TODO: You need to retrieve this data from the server, but I use
// here simple int values.
values = new ArrayList<Integer>();
for (int i = 0; i < 5; i++)
{
values.add((i % 2 == 0) ? i * 3 : i + 3);
}
//initialize the adapter, and attach it to the ListView:
adapter = new MyAdapter();
final ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
}
/**
* The onClick function of the last itemrenderer's button
* #param button the button clicked.
*/
public void loadMoreData(View button)
{
//Just put some more data into the values ArrayList:
//TODO: You need to retrieve these data from the server, as well!
for (int i = 5; i < 30; i++)
{
values.add((i % 2 == 0) ? i * 3 : i + 3);
}
//notify the ListAdapter about the changes:
adapter.notifyDataSetChanged();
}
/**
* The custom ListAdapter class used to populate the ListView
*/
private class MyAdapter extends BaseAdapter
{
private LayoutInflater inflater;
public MyAdapter()
{
inflater = LayoutInflater.from(SteppingListActivity.this);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
//check if the current item to show is the last item of the
// initial list, and if so, inflate the proper renderer for it:
if ((position == 4) && (values.size() == 5))
convertView = inflater.inflate(
R.layout.row_with_button, parent, false);
else if ((convertView == null) ||
(convertView.findViewById(R.id.loadbtn) != null))
convertView = inflater.inflate(R.layout.row, parent, false);
//set the value of the TextView
((TextView) convertView.findViewById(
R.id.textView)).setText(values.get(position)+ ".50 €");
return convertView;
}
#Override
public int getCount()
{
return values.size();
}
#Override
public Object getItem(int position)
{
return values.get(position);
}
#Override
public long getItemId(int position)
{
return position;
}
}
}
I hope you got the idea :)