Show the ActionBar while scrolling up on a ListView - java

I have a ListView and when I scroll down or up I can detect this using this solution:
listView.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) { }
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(listView.getFirstVisiblePosition() == 0)
getActionBar().show();
else
getActionBar().hide();
}
});
This way works and the ActionBar shows when the scroll comes back to the first item of the list. I would ALSO like to show the ActionBar again when I begin to scroll up within the list.
EDIT:
this is the last way and it works not always.. sometimes the actionbar disappears and never comes back:
private int mPreviousFirst;
...
listView.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) { }
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(prevVisibleItem != firstVisibleItem){
if (firstVisibleItem < mPreviousFirst)
getActionBar().show();
else
getActionBar().hide();
mPreviousFirst = firstVisibleItem;
}
}
});
i'm close but something goes wrong :(

You can do so by saving the previous first visible position each time it changes:
private int mPreviousFirst;
...
listView.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) { }
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (firstVisibleItem < mPreviousFirst) {
getActionBar().show();
} else if (firstVisibleItem > mPreviousFirst) {
getActionBar().hide();
}
mPreviousFirst = firstVisibleItem;
}
});

You can try manipulating the following onScrollChanged within your view,
onScrollChanged
which keeps track of the current and previous states of a scroll. If you are going up, then you could do the same behavior.
Something similar to the following would achieve what you are asking:
#Override
protected void onScrollChanged (int currentHorizontalPosition, int currentVerticalPosition, int oldHorizontalPosition, int oldVerticalPosition)
{
if(currentVerticalPosition < oldVerticalPosition && positionDifference > threshold)
{
getActionBar().show();
}
else //condition for downscroll or other actions.
{
getActionBar().hide();
}
}

mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
int mLastFirstVisibleItem = 0;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) { }
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getId() == mListView.getId()) {
final int currentFirstVisibleItem = mListView.getFirstVisiblePosition();
if (currentFirstVisibleItem > mLastFirstVisibleItem) {
// getSherlockActivity().getSupportActionBar().hide();
activity.hideActionBar();
} else if (currentFirstVisibleItem < mLastFirstVisibleItem) {
// getSherlockActivity().getSupportActionBar().show();
activity.showActionBar();
}
mLastFirstVisibleItem = currentFirstVisibleItem;
}
}
});
this works for me on kitkat

Related

Infinite call to "onScroll" when reach end of grid view

I've found the following code to do something when I reach the end of a gridview:
GridView gridview = (YMAnimatedGridview) v.findViewById(R.id.my_gridview);
gridview.setAdapter(adapter);
final View footerView = mainView
.findViewById(R.id.my_grid_footer_view);
gridview.setOnScrollListener(new GridView.OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount) {
// last item in grid is on the screen, show footer:
fetchMoreItems();
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
The thing is that, when I reach the end of the gridView, this method is called continously.
private void fetchMoreItems() {
Log.i(LOG_TAG, "Reached the end of grid view"); //for debbug purposes
Integer lastIndex = thumbnails.length; //This is a Bitmap array with the data I'm alredy showing
Cursor cursor = getData();
thumbnails = concat(thumbnails, new Bitmap[30]);
Integer lastIndexToRun = Math.min(30, cursor.getCount() - lastIndex);
for(int j = 0; j < lastIndexToRun; j++) {
Integer i = j + lastIndex;
cursor.moveToPosition(i);
thumbnails[i] = getThumbnail(i);
}
adapter.notifyDataSetChanged(); //This is the adapter used to fill the gridview
cursor.close();
}
I think my mistake should be in the fetchMoreItems() method, but since it's my first time using GridView, I'm not sure
You need to avoid the method to be called multiple times, like this:
private int beforeLastItem;
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
final int lastItem = firstVisibleItem + visibleItemCount;
if (lastItem == totalItemCount) {
// last item in grid is on the screen, show footer:
if (beforeLastItem != lastItem){ //to avoid multiple calls for the last item
fetchMoreItems();
beforeLastItem = lastItem;
}
} else {
beforeLastItem = lastItem;
}
}
You can use a boolean value to prevent multiple calls like this:
private final boolean isFetching = false;
GridView gridview = (YMAnimatedGridview) v.findViewById(R.id.my_gridview);
gridview.setAdapter(adapter);
final View footerView = mainView
.findViewById(R.id.my_grid_footer_view);
gridview.setOnScrollListener(new GridView.OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount && !isFetching) {
isFetching = true;
// last item in grid is on the screen, show footer:
fetchMoreItems();
}else{
if(isFetching){
isFetching = false;
}
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
You can also set isFetching to false after fetching completed.

Android Edittext Drawable click stuck focus

I have three edittext on one layout. When it's empty, then I remove the right drawable. When it isn't empty, I added the drawable. When you click to drawable, I clear the edittext.
When I clicked to rightdrawable, the cursor was stuck, and underline stay colored. Rarely I have a 2-3 cursor. Why?? What I do bad?
BAD:
GOOD:
The Layout:
<EditText
android:id="#+id/et1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="#mipmap/ic_launcher"/>
<EditText
android:id="#+id/et2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="#mipmap/ic_launcher"/>
<EditText
android:id="#+id/et3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="#mipmap/ic_launcher"/>
The MainActivity
public class MainActivity extends AppCompatActivity {
private DrawableState etstate1;
private DrawableState etstate2;
private DrawableState etstate3;
private EditText et2;
private EditText et1;
private EditText et3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et1 = (EditText)findViewById(R.id.et1);
et2 = (EditText)findViewById(R.id.et2);
et3 = (EditText)findViewById(R.id.et3);
etstate1 = new DrawableState(et1);
etstate2 = new DrawableState(et2);
etstate3 = new DrawableState(et3);
et1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (DrawableClick.isDrawableClick(motionEvent, et1, DRAWABLE_RIGHT)) {
et1.setText("");
etstate1.refreshDrawable();
return true;
}
return false;
}
});
et2.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (DrawableClick.isDrawableClick(motionEvent, et2, DRAWABLE_RIGHT)) {
et2.setText("");
etstate2.refreshDrawable();
return true;
}
return false;
}
});
et3.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (DrawableClick.isDrawableClick(motionEvent, et3, DRAWABLE_RIGHT)) {
et3.setText("");
etstate3.refreshDrawable();
return true;
}
return false;
}
});
et1.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void afterTextChanged(Editable editable) {
etstate1.refreshDrawable();
}
});
et2.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void afterTextChanged(Editable editable) {
etstate2.refreshDrawable();
}
});
et3.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void afterTextChanged(Editable editable) {
etstate3.refreshDrawable();
}
});
}
}
Helper classes:
public class DrawableClick {
public static boolean isDrawableClick(MotionEvent event, EditText editText, DrawablePositions drawablePosition) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (editText.getCompoundDrawables()[drawablePosition.position] != null && event.getX() >= (editText.getRight() - editText.getLeft() - editText.getCompoundDrawables()[drawablePosition.position].getBounds().width())) {
return true;
}
}
return false;
}
public enum DrawablePositions {
DRAWABLE_LEFT(0),
DRAWABLE_TOP(1),
DRAWABLE_RIGHT(2),
DRAWABLE_BOTTOM(3);
private int position;
DrawablePositions(int pos) {
this.position = pos;
}
}
}
Next:
public class DrawableState {
private EditText editText;
private Drawable[] editTextDrawables;
public DrawableState(EditText editText) {
this.editText = editText;
saveDrawableState();
refreshDrawable();
}
public void saveDrawableState() {
this.editTextDrawables = editText.getCompoundDrawables();
}
public void refreshDrawable() {
if (editText.getText().toString().equals("")) {
editText.setCompoundDrawables(null, null, null, null);
editText.clearFocus();
} else {
if (editTextDrawables != null) {
editText.setCompoundDrawables(editTextDrawables[0], editTextDrawables[1], editTextDrawables[2], editTextDrawables[3]);
}
}
}
I found the solution.
Change it
if (DrawableClick.isDrawableClick(motionEvent, et3, DRAWABLE_RIGHT)) {
...
return true;
}
return false;
To:
if (DrawableClick.isDrawableClick(motionEvent, et3, DRAWABLE_RIGHT)) {
...
motionEvent.setAction(MotionEvent.ACTION_CANCEL);
}
return false;

AddTextChangedListener to Loop-generated EditText views

I'm new to Android development. I'm facing a dead end developing an app for a project. Please take some time and help me out.
The problem:
I am generating some EditText views nested in a LinearLayout using a for loop.
For example:
LinearLayout rootView = (LinearLayout) findViewById(R.id.rootview);
for (int i=0,j=10;i<j;i++) {
EditText et = new EditText(this);
rootView.addView(et);
et.setHint("EditText No. "+ i);
et.setId(i);
} // This code is for example purposes only.
Now, I can't seem to understand how I can set an addTextChangedListener on the EditText that is focused at a particular time and set that text on other EditTexts. Please tell me what approach should I adopt to achieve this. I tried my best to explain the problem; however, if there is still any ambiguity, feel free to comment and ask. I'm waiting for a solution to this problem.
In terms of screenshots:
What I have:
What I want:
I hope this clears things up!
**
EDIT:
Thanks to TylerSebastian for the solution. I got it to work. Here is the final code: (Inside OnCreate() method)
final LinearLayout rootView = (LinearLayout) findViewById(R.id.rootview);
for (int i=0,j=10;i<j;i++) {
final EditText et = new EditText(this);
rootView.addView(et);
et.setHint("EditText No. "+ i);
et.setId(i);
final TextWatcher textwatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(final Editable s) {
for (int i=0;i<10;i++){
EditText view = (EditText) findViewById(i);
if (view != et){
view.setText(s.toString());
}
}
}
};
et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
et.addTextChangedListener(textwatcher);
} else {
et.removeTextChangedListener(textwatcher);
}
}
});
}
**
I don't have access to a machine with AS on it atm so no guarantee that the following is bug-free, but this should point you in the right direction:
final LinearLayout rootLayout = ...;
// within your loop
et.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void afterTextChanged(final Editable s) {
for (int i = 0; i < rootLayout.getChildCount(); i++) {
View view = rootLayout.getChildAt(i);
if (view instanceof EditText && view != et) {
((EditText) view).setText(s.toString());
}
}
}
});
edit: so the above will cause an infinite loop - see my comment below
How about:
final LinearLayout rootLayout = ...;
// again, within your loop
TextWatcher textWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void afterTextChanged(final Editable s) {
for (int i = 0; i < rootLayout.getChildCount(); i++) {
View view = rootLayout.getChildAt(i);
if (view instanceof EditText && view != et) {
((EditText) view).setText(s.toString());
}
}
}
};
et.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
((EditText) view).addTextChangedListener(textWatcher);
} else {
((EditText) view).removeTextChangedListener(textWatcher);
}
}
});
basically, only the focused element will have the textwatcher
first add a LinearLayout in your XML like that
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
then create a new class
public class EditTextCust extends RelativeLayout {
EditText status;
public EditTextCust(Context context, Model post, int inputType,TextWatcher textWatcher) {
super(context);
inflate(context, R.layout.edit_text_cust, this);
status = (EditText) findViewById(R.id.editText);
status.setInputType(inputType);
post.setData(status.getText().toString());
status.setHint(post.getHint());
status.addTextChangedListener(textWatcher);
}
public String getText() {
return status.getText().toString();
}
public EditTextCust(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextCust(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
and creat new XML file names edit_text_cust for this custom view class
<EditText
android:id="#+id/dateEditText"
android:layout_width="match_parent"
android:background="#android:color/transparent"
android:padding="#dimen/_5sdp"
android:layout_height="match_parent"
android:textSize="#dimen/_12sdp" />
and creat model class to set your data
public class Model {
String hint;
String id;
String data;
public String getHint() {
return hint;
}
public void setHint(String hint) {
this.hint = hint;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
and in your class inside the for loop but this code
Model model = new Model();
model.setHint("HINT");
model.setId("1");
editTextCust = new EditTextCust(this, editTextCustModel, InputType.TYPE_CLASS_NUMBER, new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// getText from here use
s.toString();
}
#Override
public void afterTextChanged(Editable s) {
}
});
linearLayout.addView(editTextCust);
it's work with me correctly, and if you didn't understand any thing from this code just add comment and i will help you :)

how to check first field filled then only allow next field in android

In my app, i have one spinner and two autocompletetextview. If i select value from spinner then only allow to type first autocompletetextview, If some value in first autocompletetextview then only allow to type second autocompletetextview.
How to do that.
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
autocompletetextview.setInputType(InputType.TYPE_CLASS_TEXT);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Please anyone help me!
Thanks in advance...
Try this code
autocompletetextview.setEnable(false);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
autocompletetextview.setInputType(InputType.TYPE_CLASS_TEXT);
autocompletetextview.setEnable(true);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
autocompletetextview.setEnable(false);
}
});
autocompletetextview.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
autocompletetextview2.setEnable(s.toString().trim().length() > 0 ? true : false);
}
#Override
public void afterTextChanged(Editable s) {
}
});

Syncing Two ListViews side by side Android

I'm trying to make two side by side ListViews act like a GridView to an extent. The reason I'm not using GridView is because there's no support for a Staggered Look. Anyways, I have the following code so far:
<- Old,now irrelevant code ->
EDIT:
I did as #Sam suggested and used the following code:
lv1.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (touchSource == null) {
touchSource = v;
}
if (v == touchSource) {
lv2.dispatchTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
clickSource = v;
touchSource = null;
}
}
return false;
}
});
lv1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (parent == clickSource) {
//my own code here
}
}
});
lv1.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (view == clickSource) {
}
boolean loadMore = /* maybe add a padding */
firstVisibleItem + visibleItemCount + 10 >= totalItemCount;
if (loadMore) {
//add items, load more
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
});
lv2.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (touchSource == null) {
touchSource = v;
}
if (v == touchSource) {
lv1.dispatchTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
clickSource = v;
touchSource = null;
}
}
return false;
}
});
lv2.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (parent == clickSource) {
}
}
});
lv2.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (view == clickSource) {
}
boolean loadMore = /* maybe add a padding */
firstVisibleItem + visibleItemCount + 2 >= totalItemCount;
if (loadMore) {
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
});
I am also using a header on one of the lists to create a Staggered Effect and I need to keep this stagger at all costs. This is mostly working (the above code) but it unsyncs a lot of the time. I have figured out this is only when I have small short swipes. I'm not sure why, and I can't find a good solution. It seems to me that the above logic should work.
Also, just in case it matters, I am using UniversalImageLoader to load photos and a simple EndlessScroll logic to load more photos (directly calling adapter.notifyDataSetChanged()). This stuff doesn't seem too relevant though. Even when photos are loaded, I can still see it unsyncing.
I want to be clear: if I do short swipes (and sometimes just in general repeated scrolling) I can unsync the lists at will.
Any help is appreciated. Thanks.
EDIT 2:
Yet to find a good solution. Here are the solutions that I have found that don't quite work:
The above solution: unsyncs far too often
Pinterest List View: no OnScrollListener/onItemClick differentiation
StaggeredGridView: No onScrollListener
Stag Project: No onItemClick listener
Linear Layout Method: No onItemClick Listener
Any ideas? Thanks.
Okay, so I ended up using the Linear Layout Method(See the Question) and used setTag to get the onItemClickListener working, and a CustomScrollView implementation to get the infinite List working.
Basically, two linearLayouts stacked horizontally, inside a scrollview. It works rather well, and loads much faster.
Also, to load my images SmartImageView if that helped.
If someone wants the code, I might be able to post parts of it.
Instead of listening to onTouch why don't you scroll lists in the onScroll listener of ListViews. That's what I'm using in that library with sort of tracks the scroll of a ListView similarly and it works like a charm. Check out this file. https://github.com/JlUgia/list_moving_container/blob/master/src/com/ugia/listmovingcontainer/fragment/BottomListMovingContainerFragment.java
Pay attention specially to 81 (don't forget to add the global layout updater listener) and 89 (with the onScroll Listener).
That way you can forget about the click hacks as well.
UPDATE
I'd code it the following way.
lv1.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
updateListPosition(lv2, lv1);
}
});
lv1.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
updateListPosition(lv2, lv1);
}
});
lv2.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
updateListPosition(lv1, lv2);
}
});
lv2.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
updateListPosition(lv1, lv2);
}
});
private void updateListPosition(ListView updatedList, ListView scrolledList){
updatedList.setScrollY(scrolledList.getScrollY());
}
** setScrollY already invalidates your list.
** Note that I didn't test the code. Although it should be simple enough.

Categories

Resources