two ListView not working on NavigationDrawer - java

I have two ListView in my NavigationDrawer, both of them is displayed on my NavigationDrawer, but I face a problem, when user want to click an item from one ListView, it does't work, this is how I call setOnItemClickListener from my ListView:
list_terbaru=(ListView)findViewById(R.id.list_terbaru);
list_terkirim=(ListView)findViewById(R.id.list_terkirim);
list_terbaru.setOnItemClickListener(new SlideMenuClickListener());
list_terkirim.setOnItemClickListener(new SlideMenuClickListener());
private class SlideMenuClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
switch (v.getId()) {
case R.id.list_terbaru:
id=((TextView)v.findViewById(R.id.nomor_registrasi)).getText().toString();
a=id;
ModelHelper.onModel(me);
getFragmentManager().beginTransaction().replace(R.id.frame_container,new PemegangPolis()).commit();
selectItem(position);
break;
case R.id.list_terkirim:
id=((TextView)v.findViewById(R.id.no_polis)).getText().toString();
a="";
ModelHelper.onModel(me);
getFragmentManager().beginTransaction().replace(R.id.frame_container,new PemegangPolis()).commit();
selectItembaru(position);
}
}
}
private void selectItem(int position) {
ModelHelper.onModel(me);
ModelHelper.onRetrieve(helper,id,me,position,model,SelectPemegang,SelectTertanggung,SelectUA,SelectDi,SelectDA,SelectDP);
getFragmentManager().beginTransaction().replace(R.id.frame_container,new PemegangPolis()).commit();
// helper.close();selectItem
mDrawerLayout.closeDrawer(SlidingMenu);
}
private void selectItembaru(int position) {
ModelHelper.onModel(me);
ModelHelper.onRetrieve(helper,id,me,position,model2,SelectPemegang,SelectTertanggung,SelectUA,SelectDi,SelectDA,SelectDP);
getFragmentManager().beginTransaction().replace(R.id.frame_container,new PemegangPolis()).commit();
// helper.close();selectItem
mDrawerLayout.closeDrawer(SlidingMenu);
}
so my question, is it possible to call 'onItemClick' with switch (v.getId())? and if it is possible, can anyone help me to show where is fault? and how I can solve my problem? thank you.

R.id.list_terbaru and R.id.list_terkirim are the ids of the ListViews. However v is not the ListView, but the View of the item. Switch on the id of the AdapterView (which is one of your ListViews in this case) instead:
switch (arg0.getId()) {
If there is no other error in the code (could not find one), this should solve the problem.
But have you considered creating different listeners for the lists? That way you wouldn't have to switch at all.

Related

Detect that the user is swiping away from the fragment in a viewpager

I have a survey app which is implemented using a viewpager and an arraylist of fragments. The fragments have different view types, some have radio buttons, some input boxes. I want the save the entered data to a shared variable in the parent activity when the user navigates from one fragment to another. When the user reaches the last fragment i want to display the summary of the data. i was thinking of saving the data when the user navigates from one fragment to the next. Also not sure if it is the best way to go about it.
List<Question> questions = new SurveyServiceImpl(getApplicationContext()).getSurveyQuestions(1);
ArrayList<Fragment> questionFragments = new ArrayList<>();
questionFragments.add(HomeFragment.newInstance("", ""));
for (int i = 0; i < questions.size(); i++) {
switch (questions.get(i).getQuestionType()) {
case SELECT:
if (questions.get(i).getMaximumOptionsRequired() == 1)
questionFragments.add(QuestionTypeSelect.newInstance("", questions.get(i)));
else
questionFragments.add(QuestionTypeCheckBox.newInstance("", questions.get(i)));
break;
case INPUT:
questionFragments.add(QuestionTypeInput.newInstance("", questions.get(i)));
break;
default:
}
}
questionFragments.add(EndFragment.newInstance("", ""));
final ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(), questionFragments));
Use OnPageChangeListener for: all scrolls; page centered; page scroll changes (start drag, finish center animation)
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
#Override public void onPageSelected(int position) { }
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
//User started moving current page
}});
Off the top of my head:
Save the data as soon as it is changed in each fragment :
For EditTexts, use TextWatcher : (example) to save the text when it changes in afterTextChanged().
For RadioButtons, use radioButton.setOnClickListener(/**Save data in onClick*/), or radioGroup.setOnCheckedChangeListener if you're using a RadioGroup (example).
Might not be the most efficient solution, but works :) .
Hmm. Well unless you are doing some sort of save checkmarks along the wizard flow that you want to represent that all data for that page was saved, I would not go that route personally. You can easily just recognize pageChanged listener
vpMain.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Generated method stub
}
#Override
public void onPageSelected(int position) {
setCurrentPage(position);
PAGE_TO_RETURN_TO = position;
vpMain.setCurrentItem(PAGE_TO_RETURN_TO);
validate data and allow to scroll or save
}
#Override
public void onPageScrollStateChanged(int state) {
//Generated Method Stub
}
});
but I would prefer to see onPause() of the parent activity handle saving the data personally. But it really depends on your need for the app.

Items of RecyclerView are not showing correctly

In my onBindViewHolder of my RecyclerView.Adapter<SearchAdapter.ViewHolder> when user clicks on cardview a button becomes visible. But when I'm scrolling recyclerview some other items buttons are shown as visible too. Why is this happening?
this is my code:
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
viewHolder.card.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (viewHolder.content_layout.getVisibility() == View.VISIBLE) {
viewHolder.content_layout.setVisibility(View.GONE);
viewHolder.address.setMaxLines(2);
viewHolder.attribute.setMaxLines(2);
} else {
viewHolder.content_layout.setVisibility(View.VISIBLE);
viewHolder.address.setMaxLines(8);
viewHolder.attribute.setMaxLines(8);
}
}
});
...
}
Once you start scrolling down the list your views get recycled. This means a previously inflated ViewHolder (some that gets created in onCreateViewHolder) is reused.
So what you have to do is to remember the clicked positions (e.g. via a SparseBooleanArray) and check in onBindViewHolder whether the view should be visible (previously clicked) or not.
You can find a basic usage example of the SparseBooleanArray in this StackOverflow post
The 'other' visible items buttons are the ones using the same viewholder that was modified in the callback. So because viewholders (and views) are recycled :
They should only store information that can be retrieved each time the viewholder is bound to a position.
Anything that may be changed in the views state should be refreshed in onBindViewHolder()
In your case you should store the 'is selected' somewhere else and reset the visibility and maxlines in onBindViewHolder() (not only in the callback)
Good idea is to make a class object with all data you need for one item in recycler view, also add there one boolean isItemWasClicked and inside onBindViewHolder() check this boolean and make buttons visible or not.
For example:
public class OneItemOfList{
int priceToDisplay;
String name;
String date;
boolean wasClicked;
}
public class YourAdapter extends RecyclerView.Adapter<OneItemOfList.ViewHolder> {
ArrayList<OneItemOfList> items;
...
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
viewHolder.view.setText(items.get(position).name);
if (items.get(position).wasClicked)
viewHolder.button.setVisible(View.VISIBLE);
else
viewHolder.button.setVisible(View.GONE);
viewHolder.view2.setOnClickListener(...
OnClick(...){
items.get(position).wasClicked = !items.get(position).wasClicked;
});
}
...
}
create an array for example Boolean array, and when each position clicked, set true in same position of array. and in onBindViewHolder check if that array[position] is true set that item visible if.

making onItemSelected visible to entire class

I'm new to this android/java stuff. I have this onItemSelected that will toast what has been selected in the spinner. I want to have the string resumeTableName accessible throughout my entire class that has the value of the selected spinner object. Right now it toasts the selected value however at other places in my class the resumeTableName remains null. I thought the public modifier would make it visible. How do I make this visible, do I use some sort of return?
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
// On selecting a spinner item
String resumeTableName = parent.getItemAtPosition(position).toString();
// Showing selected spinner item
Toast.makeText(parent.getContext(), resumeTableName,
Toast.LENGTH_LONG).show();
}
Use a static String resumeTableName; declared in your class and
in your onItemSelected write
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
// On selecting a spinner item
resumeTableName = parent.getItemAtPosition(position).toString();
// Showing selected spinner item
Toast.makeText(parent.getContext(), resumeTableName,
Toast.LENGTH_LONG).show();
}
In this way the value of resumeTableName updated by the method will be the same for the whole class.
If You are new in Android programming there is a nice solution for the problems with visibility of variables.
You have to create class in your package:
public class GlobalVar extends Application{
private int dummy1;
public int getDummy1() {
return dummy1;
}
public void setDummy1(int dummy1) {
this.dummy1 = dummy1;
}
}
then in any place in Your application You can get/set this data, by using:
GlobalVar gV = (GlobalVar)GetApplicationContext();
and then You just modify them by using Getters/Setters or any public methods from this class. I think it's very good solution for set of variables that You use often from different places of code.

Adding a Button on a View

I am going nuts over this.
I did not find any working solution (tried a few from stackoverflow)
Scenario (this is an actual screenshot what is already done):
I have a Activity that has a View as his Attribute.
This view adds another view via View.addView(myView).
I now want to add a Button to myView (to be specific: after MotionEvent.ACTION_UP the button should appear in the right lower corner (this will start the robot to drive the track))
Here is a shortcut of my code:
public class ModeRouting extends View {
public ModeRouting(Context context) {
super(context);
Button asuroStartButton = new Button(context) //does not work
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int actionevent = event.getAction();
if (actionevent == MotionEvent.ACTION_UP
|| actionevent == MotionEvent.ACTION_CANCEL) {
asuroStartButton.visible=true;
view.add(asuroStartButton);
}
return true;
}
}
and my Activity:
//in constructor
contentView = (FrameLayout) findViewById(R.id.content);
onClickListenerFacade(routingMode, route);
//this removes all views from stack and places the new one on the view
private void onClickListenerFacade(View v, final View target) {
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
contentView.removeAllViews();
contentView.setBackgroundColor(0xff000000);
contentView.addView(target);
modeSelectorAnimation();
}
});
}
I tried to create a button in my mainactivity.xml and instantiate in my mainactivity.
I am missing some point in here but i am not sure which.
Since my view is purely dynamic (no layout.xml) i dont think i should use a layout.xml (maybe thats my mind-blockage) but instead set the button attributes dynamically too.
Any hint is appreciated!
You want to extend ViewGroup rather than just a View (LinearLayout, RelativeLayout, FrameLayout, etc) - they handle child views for you.
I think maybe you need to refresh the whole view/activity. Try to do this in the onResume methode, maybe this helps. But as you don't use a layout.xml, I'm not sure if this helps you much..
#Override
protected void onResume(){
super.onResume();
setContentView(R.layout.activity_main);
}

Drag and Drop in a `ListView`

I am trying to implement a drag and drop in a ListView in android(Ice Cream Sandwich). So when the dragged object reaches the edge of the ListView, I am scrolling the ListView in the relevant direction. The problem is that when we scroll, sometimes the adapter creates new Views as necessary and these 'new' Views did not receive the ACTION_DRAG_STARTED event earlier and hence do not receive the DragEvent updates. Is there any way I can send the events to these views as well?
An easiest way to implement drag and drop in listview is you use this great library.
https://github.com/commonsguy/cwac-touchlist
it's worth trying.
Looking at the source for View, I see:
static final int DRAG_CAN_ACCEPT = 0x00000001;
int mPrivateFlags2;
boolean canAcceptDrag() {
return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
}
mPrivateFlags2 is package-private and not exposed by the SDK. However, you should be able to change it in a subclass by doing:
try {
Field mPrivateFlags2 = this.getClass().getField("mPrivateFlags2");
int currentValue = mPrivateFlags2.getInt(this);
mPrivateFlags2.setInt(this, currentValue | 0x00000001);
} catch (Exception e) {
}
I have the same problem. I did not solved this recycling problem, but I found a possible workaround still using the Drag & Drop framework. The idea is to change of perspective: instead of using a OnDragListener on each View in the list, it can be used on the ListView directly.
Then the idea is to find on top of which item the finger is while doing the Drag & Drop, and to write the related display code in the ListAdapter of the ListView. The trick is then to find on top of which item view we are, and where the drop is done.
In order to do that, I set as an id to each view created by the adapter its ListView position - with View.setId(), so I can find it later using a combination of ListView.pointToPosition() and ListView.findViewById().
As a drag listener example (which is, I remind you, applied on the ListView), it can be something like that:
// Initalize your ListView
private ListView _myListView = new ListView(getContext());
// Start drag when long click on a ListView item
_myListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(null, shadowBuilder, _myListView.getItemAtPosition(position), 0);
return true;
}
});
// Set the adapter and drag listener
_myListView.setOnDragListener(new MyListViewDragListener());
_myListView.setAdapter(new MyViewAdapter(getActivity()));
// Classes used above
private class MyViewAdapter extends ArrayAdapter<Object> {
public MyViewAdapter (Context context, List<TimedElement> objects) {
super(context, 0, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View myView = convertView;
if (myView == null) {
// Instanciate your view
}
// Associates view and position in ListAdapter, needed for drag and drop
myView.setId(position);
return myView;
}
}
private class MyListViewDragListener implements View.OnDragListener {
#Override
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
return true;
case DragEvent.ACTION_DRAG_DROP:
// We drag the item on top of the one which is at itemPosition
int itemPosition = _myListView.pointToPosition((int)event.getX(), (int)event.getY());
// We can even get the view at itemPosition thanks to get/setid
View itemView = _myListView.findViewById(itemPosition );
/* If you try the same thing in ACTION_DRAG_LOCATION, itemView
* is sometimes null; if you need this view, just return if null.
* As the same event is then fired later, only process the event
* when itemView is not null.
* It can be more problematic in ACTION_DRAG_DROP but for now
* I never had itemView null in this event. */
// Handle the drop as you like
return true;
}
}
}
Now if you need to have a visual feedback when doing a drag and drop, there are several strategies. You can for instance have 2 instance variables in your activity named:
private boolean ongoingDrag = false; // To know if we are in a drag&drop state
private int dragPosition = 0; // You put the itemPosition variable here
When doing the drag and drop in MyListViewDragListener you modify these variables, and you use their state in MyViewAdapter. Of course do not forget to update the UI (in the event thread of course, use a Handler) with something like _myListView.getAdapter()).notifyDataSetChanged() or maybe _myListView.invalidate() method.
The problem is because listView.getPositionForView(view) returns -1 if the view is not visible when it is called. So relying on that will fail when you scroll the list. So, instead of setting a view.setOnLongClickListener() you can set a listView.setOnItemLongClickListener() on the list item which calls startDrag() on the item. onItemLongClick() gives you the position which you can pass to in the myLocalState parameter of startDrag(). Then you recover that in onDrag() using event.getLocalState() and casting it to an Integer. Like this...
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
position -= listView.getHeaderViewsCount();
DragShadowBuilder dragShadow = new View.DragShadowBuilder(view);
view.startDrag(null, dragShadow, position, 0);
return true;
}
});
Then in your OnDragListener...
#Override
public boolean onDrag(View eventView, DragEvent event) {
Integer dragViewPos = ((Integer) event.getLocalState());
int eventViewPos = listView.getPositionForView(eventView) - listView.getHeaderViewsCount();
...
}

Categories