I am trying to populate data in UI fetched through REST service. The data comes up everytime but the UI doesn't get populated sometimes. The UI is kind of listing but listview is not being used. There's a ScrollView which has LinearLayout as its child and then row views are added to the linearlayout. There are times when UI just doesn't get updated even if the data is passed to it.
private void showData(List list) {
if(list != null && list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
} else {
mNoData.setVisibility(View.GONE);
final LinearLayout linearLayout = (LinearLayout) findViewById(R.id.details_layout);
findViewById(R.id.details_progress).setVisibility(View.GONE);
linearLayout.removeAllViews();
LayoutInflater layoutInflater = getLayoutInflater();
View rowView = null;
TextView txtName = null;
Button buttonPlay = null;
for (int i = 0; i < list.size(); i++) {
rowView = layoutInflater.inflate(R.layout.row_view, null);
txtName = (TextView) rowView.findViewById(R.id.row_view_name);
buttonPlay = (Button) rowView.findViewById(R.id.row_view_button_play);
final Item item = (Item) list.get(i);
rowView.setTag(i) ;
txtName.setText(item.getName());
final RecentItem recentItem = RecentsManager.getInstance().getRecentItemFromRefID(item.getId());
if (recentItem !=null) {
buttonPlay.setText(getString("Resume"));
buttonPlay.requestFocus();
}
buttonPlay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (recentItem!=null) {
//do some action
} else {
//do some action
}
finish();
}
});
final int tag = (Integer) rowView.getTag() ;
rowView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do some action
}
}) ;
txtName.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do some action
}
});
buttonPlay.setId(i);
if(i < list.size())
buttonPlay.setNextFocusDownId(i+1);
linearLayout.addView(rowView);
if (i == 0) {
buttonPlay.requestFocus();
buttonPlay.setNextFocusUpId(mButtonReminder.getId());
if(mButtonReminder != null) {
mButtonReminder.setNextFocusDownId(buttonPlay.getId());
}
} else {
buttonPlay.setNextFocusUpId(i-1);
}
}
}
}
I have even checked the linearlayout children's count and the count is always equal to list size which means rows are also being added to it but it just doesn't show up on the UI.
What can be the issue?
you are using condition
if(list != null && list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
}
change it to
if(list == null || list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
}
I was able to resolve the issue by doing certain changes as adding fillViewPort="true" for scrollview. Also, there was a background thread which was trying to update the UI because of which UI thread was breaking. This didn't resulted in a crash but the UI updation didn't happened. With these two changes it's working fine.
Related
I want select only one radio button in recyclerView and get its data in its Activity.
I have gone through following solutions :
Single selection in RecyclerView
Select only one radiobutton in a recyclerview
And I made one solution :
private static int lastCheckedPos = -1;
binding.radioButton.setChecked(mImagesList.get(position).isSelected());
binding.radioButton.setTag(new Integer(position));
//for default check in first item
if(position == 0 && mImagesList.get(0).isSelected() && binding.radioButton.isChecked())
{
radioButton = binding.radioButton;
lastCheckedPos = 0;
}
binding.radioButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
RadioButton cb = (RadioButton)v;
int clickedPos = ((Integer)cb.getTag()).intValue();
if(cb.isChecked())
{
if(radioButton != null)
{
radioButton.setChecked(false);
mImagesList.get(lastCheckedPos).setSelected(false);
}
radioButton = cb;
lastCheckedPos = clickedPos;
}
else
radioButton = null;
mImagesList.get(clickedPos).setSelected(cb.isChecked());
}
});
I have written this in onBindViewHolder method.
Now to get data i have written this in adapter :
public String getUserId() {
if(lastCheckedPos == -1)
{
return null;
} else {
return mImagesList.get(lastCheckedPos).getUser_code();
}
}
And get this in activity :
userId = adapter.getUserId();
But I am not able to get any data in activity. It is always showing null. Also if I click twice on radio button then it deselected.
Please ask if anything unclear. Any help would be appreciated.
Thank you :)
Replace int clickedPos = ((Integer)cb.getTag()).intValue(); by int clickedPos =position;
Can someone please explain why the first piece of code here works but not the last piece? The only difference is the index of which i insert my view, i-1 and i+1. Is i+1 just not possible with index? I can write any other number in there and it works.
upButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < drawerViewGroup3.getChildCount(); i++) {
View view = drawerViewGroup3.getChildAt(i);
TextView tv = (TextView) view.findViewById(R.id.drawer_name);
if (tv.getText().toString().equals(drawerName.getText().toString()) && i != 0) {
drawerViewGroup3.removeView(view);
drawerViewGroup3.addView(view, i - 1);
}
}
}
});
downButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < drawerViewGroup3.getChildCount(); i++) {
View view = drawerViewGroup3.getChildAt(i);
TextView tv = (TextView) view.findViewById(R.id.drawer_name);
if (tv.getText().toString().equals(drawerName.getText().toString())) {
drawerViewGroup3.removeView(view);
drawerViewGroup3.addView(view, i + 1);
}
}
}
});
Some context on the app. I have a vertical oriented LinearLayout with multiple LinearLayouts inside. When clicking the two Buttons in the code, one of the children is to move up or down, switching their positions.
EDIT: Ok so I figured it out.
downButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View viewToMove = null;
int viewToMovePos = drawerViewGroup3.getChildCount();
for (int i = 0; i < drawerViewGroup3.getChildCount(); i++) {
View view = drawerViewGroup3.getChildAt(i);
TextView tv = (TextView) view.findViewById(R.id.drawer_name);
if (tv.getText().toString().equals(drawerName.getText().toString()) && i != drawerViewGroup3.getChildCount() - 1) {
viewToMovePos = i;
viewToMove = view;
}
}
alert.dismiss();
if (viewToMovePos != drawerViewGroup3.getChildCount()) {
drawerViewGroup3.removeView(viewToMove);
drawerViewGroup3.addView(viewToMove, viewToMovePos + 1);
}
}
});
Not the prettiest code and probably not gonna help others as it's very specific, but that was the answer.
When you remove a view from your LinearLayout, the view at index i is now the view which was after the one which you removed. Then you add a view at i - 1 which is before this view (the one which was previously after the removed view). The final result is that you remove a view and insert back where it used to be.
Instead, you need to add the view at i - 2.
I suggest that you look at RecyclerView. It is specifically designed to efficiently create a dynamic list of views for given data. You only have to manipulate the data and RecyclerView does all the hard work for you.
I'm facing a strange behaviour using an ArrayAdapter.
When the number of listview item exceed the height of the listView (say after item 8), the next item get the id 0 instead the id 9.
In my opinion this type of issue was explained here with the convertView, but i use it in the same way (i think).
The following code is my ArrayAdapter.
public class StepsAdapter extends ArrayAdapter<String> {
Context context;
List<String> steps;
public StepsAdapter(Context context, int resourceId, List<String> steps) {
super(context, resourceId, steps);
this.context = context;
}
private class ViewHolder {
EditText stepValue;
ImageView removeStep;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final String step = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row_step, null);
holder = new ViewHolder();
holder.stepValue = (EditText) convertView.findViewById(R.id.stepEdit);
holder.removeStep = (ImageView) convertView.findViewById(R.id.removeStep);
holder.stepValue.setText(step);
holder.removeStep.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"* Remove id step " + position, Toast.LENGTH_LONG).show();
steps.remove(position);
notifyDataSetChanged();
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
Then my main activity where i get existing data and put it in my listView, the add button and the save button.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_game);
mContext = getApplicationContext();
steps = new ArrayList<String>();
stepsAdapter = new StepsAdapter(mContext,R.layout.row_step,steps);
Gson gson = new GsonBuilder().create();
game = gson.fromJson(gameJson, Games.class);
/*
* Settings values
*/
gameNameValue.setText(game.getName());
gameBackgroundPreview.setBackgroundColor(game.getColor());
colorSelected = game.getColor();
for(int i = 0; i < game.getSteps().size() ; i++){
//steps.add(game.getSteps().get(i).toString());
//notifyDataSetChanged();
stepsAdapter.add(game.getSteps().get(i).toString());
}
final ListView listSteps = (ListView) findViewById(R.id.listViewSteps);
listSteps.setAdapter(stepsAdapter);
gameNameValue.setText(gameName);
addSteps.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stepsId = steps.size();
Toast.makeText(getApplicationContext(), "addSteps : " + stepsId, Toast.LENGTH_LONG).show();
stepsAdapter.insert("newstep", stepsId);
}
});
buttonSaveGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String valueEditGameName = gameNameValue.getText().toString();
int valueColorBackaground = colorSelected;
String picture = "testPic";
for(int i=0; i < listSteps.getChildCount(); i++) {
LinearLayout rowLayout = (LinearLayout) listSteps.getChildAt(i);
//Log.e(TAG, ">> :) layout >>" + listSteps.getChildAt(i).getClass().getName());
EditText editRow = (EditText) rowLayout.getChildAt(0);
stepsValues.add(editRow.getText().toString());
//Log.e(TAG, ">> :) inside layout >>" + editRow.getText().toString());
}
if(valueEditGameName.trim().length() > 0 && picture.trim().length() >0 ){
Games game = new Games(valueEditGameName,valueColorBackaground,picture,stepsValues);
String goToSave = game.createJson();
Log.e(TAG, ">>Saved>>" + goToSave);
final CkdFile file = new CkdFile();
String saved = file.writeToSDFile(game.getName(), goToSave);
Toast.makeText(mContext, saved, Toast.LENGTH_LONG).show();
Intent backToMain = new Intent(mContext,MainActivity.class);
startActivity(backToMain);
} else {
Toast.makeText(mContext, "Fill all texts", Toast.LENGTH_LONG).show();
}
}
});
}
I try to add items in 2 different ways :
add item through : List steps
add item through : StepsAdapter stepsAdapter
Both give me same behaviour.
If someone has a clue to help understanding what i'm doing wrong with my implementation of ListView/ArrayAdapter.
Thanks in advance !
EDIT 1 :
After pushing some logs everywere, it understand the strange behaviour :
My adapter have only 6 slots (the limit came from the size of the listview in layout), and when my arraylist have more than 6 items, the getView select items only between 0 and 5.
I'm searching now a way to get the position in ArrayList and not the position in arrayadapter.
I faced same issue recently. Add following overrides to Adapter:
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
I found a simple xml "trick" to avoid this behaviour : i set a biger height to listView.
<ListView
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_gravity="center_horizontal"
android:id="#+id/listViewSteps"
android:layout_margin="10dp">
</ListView>
It's not really resolve but a take it ...
I'm trying to make my first app which has a set of 15 buttons. when you press a button the color changes between two numbers.Then if you press a specificity different "commit" button the buttons won't change colors any more.
My question right now is how would I be able to iterate through the buttons on the screen? I believe I need a assign the buttons a "name", "type", or something like it, and then find all instances where that happens but I cannot find the relevant getter/setter methods.
Here is my code so far:
public void clickHandler(View view) {
Button btn = (Button) view;
int id = btn.getId();
boolean clicked = isChosen(btn);
if( clicked == true && id != 1) {
btn.setBackgroundColor(-3355444);
}
else{
btn.setBackgroundColor(-16777216);
}
}
public boolean isChosen(Button btn){
ColorDrawable buttonColor = (ColorDrawable) btn.getBackground();
int colorId = buttonColor.getColor();
if(colorId == -16777216){
return true;
}
else return false;
}
public boolean player = true;
public void changeTurn(View view) {
TextView t = (TextView) findViewById(R.id.textView3);
if(player == false) {
t.setText("Player 2's turn");
player = true;
}
else{
t.setText("Player 1's turn");
player = false;
}
Hope this piece of code helps
final int buttonCount = 15;
LinearLayout mLayout = (LinearLayout) findViewById(R.id.pager);
for (int i = 0; i < buttonCount; i++) {
TextView textView = new TextView(this);
textView.setTag(String.valueOf(i));
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int buttonID = Integer.valueOf(view.getTag().toString());
updateColorForButtonAtPosition(buttonCount);
}
});
mLayout.addView(textView);
}
private void updateColorForButtonAtPosition (int buttonCount){
// add your functionality here
}
I've looked for this issue but nothing I've found matches my situation.
My problem occurs onAndroid 2.3.x (on 4.x it works perfectly)
I have an application with a custom list view. I initialize my listview as follows
ListAdapter mListAdapter = new ListAdapter(getApplicationContext(), this, ...);
lvSelector = (ListView) findViewById(R.id.listView1);
lvSelector.setAdapter(mListAdapter);
My ListAdapter is as follows:
public class ListAdapter extends BaseAdapter {
static class Holder {
LinearLayout layoutRoot, layoutColor;
TextView hText;
Animation anim = AnimationUtils.loadAnimation(mActivity, R.anim.anim_list_item);
public Holder() {
layoutRoot = new LinearLayout(mContext);
layoutColor = new LinearLayout(mContext);
hText = new TextView(mContext);
}
public Holder(Holder holder) {
this.layoutRoot = holder.layoutRoot;
this.layoutColor = holder.layoutColor;
this.hText = holder.hText;
}
}
int mSwap1, mSwap2;
Animation mAnimation;
public ListAdapter(Context _context, Activity _activity, FileHandler _fileHandler, String _strSchemaName, List<String> _list, List<String> _solution) {
mContext = _context;
mActivity = _activity;
mAnimation = AnimationUtils.loadAnimation(mActivity, R.anim.anim_list_item);
mAnimation.reset();
mSwap1 = mSwap2 = -1;
/* ... */
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int fPosition = position;
View row = convertView;
Holder lHolder = null;
if (row==null) {
LayoutInflater inflater = mActivity.getLayoutInflater();
row = inflater.inflate(R.layout.layout_schema_element, parent, false);
lHolder = new Holder();
lHolder.layoutRoot = (LinearLayout) row.findViewById(R.id.elementLayoutRoot);
lHolder.layoutColor = (LinearLayout) row.findViewById(R.id.elementLayoutColor);
lHolder.hText = (TextView) row.findViewById(R.id.textViewWord);
row.setTag(lHolder);
}
else {
lHolder = (Holder)row.getTag();
}
row.setOnClickListener(null);
if (position==0 || position==mDataList.size()-1) {
lHolder.layoutColor.setBackgroundResource(R.drawable.bg_elem_fixed);
lHolder.layoutColor.setOnClickListener(null);
}
else {
lHolder.layoutColor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
moveElement(fPosition);
}
});
}
lHolder.hText.setText(mDataList.get(position));
lHolder.layoutRoot.setBackgroundResource(0);
mHolder.set(position, lHolder);
return row;
}
}
protected void moveElement(int _element) {
if (mDataList.get(_element).equals(mSolution.get(_element)))
return;
if (mSwap1==-1)
{
System.out.println("setting swap1=" + _element);
mHolder.get(_element).layoutRoot.setBackgroundResource(R.drawable.bg_elem_selected_lite);
mSwap1 = _element;
}
else
{
if (mSwap2==-1)
{
System.out.println("setting swap2=" + _element);
mHolder.get(_element).layoutRoot.setBackgroundResource(R.drawable.bg_elem_selected_lite);
mSwap2 = _element;
}
}
if (mSwap1!=-1)
{
System.out.println("running animation on mSwap1=" + mSwap1);
mHolder.get(mSwap1).layoutRoot.clearAnimation();
mHolder.get(mSwap1).layoutRoot.startAnimation(mAnimation);
}
/***** THIS IS WHAT DOES NOT WORK *****/
if (mSwap2!=-1)
{
System.out.println("running animation on mSwap2=" + mSwap2);
mHolder.get(mSwap2).layoutRoot.clearAnimation();
mHolder.get(mSwap2).layoutRoot.startAnimation(mAnimation);
}
if (mSwap1!=-1 && mSwap2!=-1)
{
mHolder.get(mSwap1).layoutRoot.setBackgroundColor(0);
mHolder.get(mSwap2).layoutRoot.setBackgroundColor(0);
if (mSwap1==mSwap2)
{
mSwap1 = mSwap2 = -1;
return;
}
Collections.swap(mDataList, mSwap1, mSwap2);
Collections.swap(mHolder, mSwap1, mSwap2);
Collections.swap(dataObjs, mSwap1, mSwap2);
mSwap1 = mSwap2 = -1;
notifyDataSetChanged();
}
}
}
Everything works fine when I perform Collections.swap(list, mSwap1, mSwap2), elements are correctly swapped.
First animation (mSwap1) is run fine; my problem is that when second animation is run (mSwap2), it is executed on another element in screen even if mSwap2 is right (e.g.: mSwap1=1 -> second element in list is animated, mSwap2=2 -> n-1 element and n-2 element in list are animated where n is the number of visible elemnts).
I've solved my problem replacing animation calls
mHolder.get(idx).layoutRoot.clearAnimation();
mHolder.get(idx).layoutRoot.startAnimation(mAnimation);
with the following method
private void animateItem(int _index, Animation _animation) {
if (
_index<mLvSelector.getFirstVisiblePosition() // selected item is above first visible element
|| _index>mLvSelector.getLastVisiblePosition() // selected item is below last visible element
)
// element is invisible -> no animation
return;
int newIndex = _index;
if (
android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH // before android 4.0
&& mSwap2>=0 // second selection
&& mSwap1!=mSwap2 // second selection differs from first selection
)
newIndex = mLvSelector.getFirstVisiblePosition() + (mLvSelector.getLastVisiblePosition() - _index);
mHolder.get(newIndex).layoutRoot.clearAnimation();
mHolder.get(newIndex).layoutRoot.startAnimation(_animation);
}
Adding Animation argument to the method allows to differentiate animation between elements (mSwap1 and mSwap2).