Scroll from bottom to top does not work using SwipeRefreshLayout - java

I have implemented SwipeRefreshLayout and it works fine basically. https://developer.android.com/training/swipe/add-swipe-interface.html
I am facing weired issue when you go to the bottom of the list and when you try to scroll to top the SwipeRefreshLayout refreshes.
That is not what I need. I need just scroll to the top of the List and not refresh the ListView.
I mean it should be some condition when to refresh depending where we stand. Right? Because the expecting behavior is allow refresh when we at the top of the ListView.
Please help.
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout 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"
android:orientation="vertical"
>
<SearchView
android:id="#+id/editSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:iconifiedByDefault="false"
android:queryHint="Input the number"
/>
<ListView
android:paddingTop="5dp"
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
And the code
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment_two, container, false);
swiperefresh = (SwipeRefreshLayout) view.findViewById(R.id.swiperefresh);
swiperefresh.setColorScheme(R.color.colorPrimary, R.color.colorAccent, R.color.colorPrimaryDark, R.color.colorPrimary);
swiperefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
swiperefresh.setRefreshing(true);
Log.d("Swipe", "Refreshing Number");
// Get data from WebAPI or database cache
}
});
return view;
}

Well... Finally I found solution here Scroll up does not work with SwipeRefreshLayout in Listview
So my layout is not gonna be changed but the code yes.
We have to do following
Implement AbsListView.OnScrollListener like public
class FragmentTwo extends ListFragment implements SearchView.OnQueryTextListener, AbsListView.OnScrollListener
Add two methods of the implemented interface AbsListView.OnScrollListener
like here
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
swiperefresh.setEnabled(firstVisibleItem == 0);
}
And the key here is
swiperefresh.setEnabled(firstVisibleItem == 0);
implements OnScrollListener inside listFragment

this library allows you to choose between pull-up and pull-down :
https://github.com/chrisbanes/Android-PullToRefresh
Pull Up to Refresh
By default this library is set to Pull Down to Refresh, but if you want to allow Pulling Up to Refresh then you can do so. You can even set the View to enable both Pulling Up and Pulling Down using the 'both' setting. See the Customisation page for more information on how to set this.
I don't think the SwipeRefreshLayout does allow that.

Related

ArrayAdapter additions not showing in ListView

I have a Android fragment containing a ListView, and I have attached an ArrayAdapter to the ListView, but when I insert items into the ArrayAdapter, the ListView only shows the first item.
onCreateView iterates over my Technologies, if they're unlocked, it adds them to the ArrayList shownTechs, but only the first item ever appears
public class TabTechnologyList extends Fragment {
private static final String TAB_NAME = "tab_name";
private ListView techList;
private ArrayList<Technology> shownTechs = new ArrayList<>();
ArrayAdapter<Technology> techListAdapter;
public TabTechnologyList() { }
public static TabTechnologyList newInstance() {
TabTechnologyList fragment = new TabTechnologyList();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tabData = Globals.getTabData();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_technology_list, container, false);
techList = (ListView) view.findViewById(R.id.tabTechListList);
techListAdapter = new ArrayAdapter<>(getActivity().getApplicationContext(), R.layout.layout_techlist_element, shownTechs);
techList.setAdapter(techListAdapter);
for(Technology tech: tabData.getTechnologies()) {
shownTechs.add(tech);
}
//Only the first one is shown on the screen
return view;
}
}
}
When I google for similar issues, people seem to be recreating the ArrayAdapter instead of editing the existing one, but I'm not doing that, and cant' figure out what problem remains. Any suggestions?
fragment_technology_list.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"
tools:context="com.tbohne.kittens.front.TabTechnologyList"
>
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/tabTechListList" />
</RelativeLayout>
layout_techlist_element.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TextView>
Addition
I have just realized that this fragment is not filling the parent height, and is only tall enough to show the one entry, as if the fragment height were wrap_content. (I can't scroll it, so it appears as if there's only the one). This makes me think the nesting of fragments may be related, so here's the code that creates the fragment:
public class TabTechnology extends Fragment {
private TabTechnologyList table;
private OnFragmentInteractionListener mListener;
public TabTechnology() {}
public static TabTechnology newInstance(String tabName) {[SNIP]}
#Override public static onAttach(Activity activity) {[SNIP]}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_technology, container, false);
table = TabTechnologyList.newInstance(tabName);
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.view_table, table);
transaction.commit();
return view;
}
}
fragment_technology.xml
<LinearLayout 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"
tools:context="com.tbohne.kittens.front.TabTechnology"
android:orientation="vertical">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:id="#+id/view_table"
android:layout_above="#+id/view_details" />
<View android:layout_width="match_parent"
android:layout_height="1px"
android:background="?android:attr/listDivider" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:id="#+id/view_details"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true" />
</LinearLayout>
Putting the Fragment inside the ScrollView was the source of the problem. Simply replaced those with FrameLayout, and suddenly everything magically works. Very strange.
I suspect the problem has something to do with nesting scrollable objects.

ListView Shared Element Transition Issue

I am attempting to create shared element transition between two Activities. This appears to work find between two layouts, each containing a single ImageView. However, I am having issues getting this transition to work with a ListView.
The issue is when the user taps on the first row, the transition will work as expected. However, when the second row is tapped, the origin of the transition appears to be the image of the first row as well!
I have created a simple list view with a custom row layout:
row_detailed.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Daft Punk"
android:id="#+id/primary_textview"
android:layout_gravity="center_horizontal"
android:layout_weight="0.07"
android:layout_alignTop="#+id/primary_imageview"
android:layout_toRightOf="#+id/primary_imageview" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Random Access Memories"
android:id="#+id/textView4"
android:layout_gravity="center_horizontal"
android:layout_weight="0.07"
android:layout_alignBottom="#+id/primary_imageview"
android:layout_toRightOf="#+id/primary_imageview" />
<ImageView
android:layout_width="84dp"
android:layout_height="84dp"
android:id="#+id/primary_imageview"
android:src="#drawable/ram"
android:layout_weight="0.07" />
</RelativeLayout>
The layout for the secondary Activity, activity_transition_secondary.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:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="legiocode.com.tapstrprototype.activity.TransitionSecondaryActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/secondary_imageview"
android:src="#drawable/ram"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
The Primary Activity, TransitionPrimaryActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transition_primary);
ListView listView = (ListView)findViewById(R.id.listView2);
ArrayAdapter<String> adapter = new ArrayAdapter(this,
R.layout.row_detailed,
R.id.primary_textview,
items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String transitionName = getString(R.string.transition_image) + String.format("_%d", i);
ImageView imageView = (ImageView)findViewById(R.id.primary_imageview);
imageView.setTransitionName(transitionName);
Intent intent = new Intent(TransitionPrimaryActivity.this, TransitionSecondaryActivity.class);
intent.putExtra(TransitionSecondaryActivity.TRANSITION_NAME, transitionName);
ActivityOptionsCompat options =
ActivityOptionsCompat.makeSceneTransitionAnimation(TransitionPrimaryActivity.this,
imageView, // The view which starts the transition
transitionName // The transitionName of the view we’re transitioning to
);
ActivityCompat.startActivity(TransitionPrimaryActivity.this, intent, options.toBundle());
}
});
}
The Secondary Activity, TransitionSecondaryActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transition_secondary);
String transitionName = getIntent().getStringExtra(TRANSITION_NAME);
ImageView imageView = (ImageView)findViewById(R.id.secondary_imageview);
imageView.setTransitionName(transitionName);
}
I have tried to implement the transition names dynamically, but that doesn't seem to make much of a difference. Am I setting up the transition correctly?
You have to access your actually clicked View (in this case parameter view) in
onItemClick(AdapterView<?> adapterView, View view, int i, long l)
With
ImageView imageView = (ImageView)findViewById(R.id.primary_imageview);
you always access the first element in the list.
PS: Put the transition names inside the xml. Makes it much more easy to read.

ListFragment appearing twice on phone

I'm seeing an undesired appearance of my list fragment when I run my app on the phone emulator. On the tablet emulator it appears once but on the phone emulator it appears twice. How can I fix this error for the list to appear on the phone emulator only once?
MainActivity.java
public class MainActivity extends ActionBarActivity {
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentMainList newFragment = new FragmentMainList();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.master_container, newFragment);
transaction.commit();
if (findViewById(R.id.detail_container) != null) {
mTwoPane = true;
}
}
}
activity_main.xml
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/master_container"
android:name="com.apptacularapps.exitsexpertlondonlite.FragmentMainList"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentMainList"
tools:layout="#android:layout/list_content"/>
activity_main.xml (sw600dp)
<LinearLayout 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:orientation="horizontal"
android:showDividers="middle"
tools:context=".MainActivity" >
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/master_container"/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:id="#+id/detail_container"/>
</LinearLayout>
FragmentMainList.java
public class FragmentMainList extends android.support.v4.app.Fragment {
ListView list_main;
String[] listContent = {
"Item 1",
"Item 2",
"Item 3"
};
private boolean mTwoPane;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.fragment_main_list, container, false);
list_main = (ListView)v.findViewById(R.id.list_main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1,listContent);
list_main.setAdapter(adapter);
return v;
}
}
Please move the logic to add fragment inside the if loop you have.
Although you've already understood how to make it work, I'll try to explain how to make it work properly.
What you do is in fact this:
If on small screen - add the fragment statically (in XML)
If on larger screen - add the fragment dynamically (with FragmentTransaction)
It looks weird that the method by which you get the desired functionality depend on the screen size - there should be no correlation between these factors.
What you ought to do (IMHO) is to add this fragment dynamically in both cases - just change your Fragment tag in the first XML to FrameLayout and everything will work as expected.

ListFragment: Runtime error "Your content must have a ListView whose id attribute is 'android.R.list'

I have a listfragment class:
public class activityfeedScreen extends ListFragment implements OnItemClickListener {
private ListView activityfeed_feedList_listView;
private ActivityFeedBaseAdapter adapter;
public static final activityfeedScreen newInstance()
{
activityfeedScreen fragment = new activityfeedScreen();
Bundle bdl = new Bundle(1);
fragment.setArguments(bdl);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_activityfeed_screen, container, false);
activityfeed_feedList_listView = (ListView)v.findViewById(R.id.activityfeed_feedList_listView);
activityfeed_feedList_listView.setAdapter(adapter);
activityfeed_feedList_listView.setOnItemClickListener(this);
return v;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void onItemClick(AdapterView<?> activityfeedlistview, View view, int position, long itemID) {
Intent intent_activityfeed_showitemdescription = new Intent(view.getContext(), activityfeedItemScreen.class);
startActivity(intent_activityfeed_showitemdescription);
}
}
In this class I am getting an error at the line:
activityfeed_feedList_listView = (ListView)v.findViewById(R.id.activityfeed_feedList_listView);
I initially thought it was a problem due to the getView() being null so I moved that from the onCreate method to the onCreateView() method. But I am getting the runtime error as stated in the title.
Here is my layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:background="#E5E5E5"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp">
<ImageView
android:id="#+id/activityfeed_profilePicture_imageView"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:src="#drawable/default_profile"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#B9B9B9"
android:layout_marginTop="20dp">
<ListView
android:id="#+id/activityfeed_feedList_listView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</RelativeLayout>
I understand that I must change the listview id to
android:id="#android:id/list"
but I am not sure then how to call that in my onCreateView method.
Thanks for all your help!
Yes. First of all you do have to change the ID of your ListView like so:
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
In your onCreateView you can reference the ID by android.R.id.list. This is because Android built-in resource reside in android.R. You can also find there drawables, styles, etc. (you can call them in a similar maneer).
Taking the above into consideration, your onCreateView method should look like this :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_activityfeed_screen, container, false);
activityfeed_feedList_listView = (ListView)v.findViewById(android.R.id.list);
activityfeed_feedList_listView.setAdapter(adapter);
activityfeed_feedList_listView.setOnItemClickListener(this);
return v;
}
That's all ;)
In onCreateView() you need to provide a layout that has a ListView with and id of #android:id/list.
ListFragment provides some helper methods (e.g setListAdapter()) that require the layout to have a ListView with that id so it can reference it and set the adapter for you.

ListView setOnItemClickListener doesn't work on Switch widget

i'm trying to catch the click event for a list of Switches
ListView list = (ListView) findViewById(R.id.main_view);
ArrayAdapter<String> LTRadapter = new ArrayAdapter<String>(this, R.layout.list_main_view_item, R.id.switch1, values);
list.setAdapter(LTRadapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
Log.w("MiniTasker","w00t " + Integer.toString(pos));
}
});
i've added android:descendantFocusability="blocksDescendants" to the ListView but to no avail.
Here's activity_main.xml:
<LinearLayout 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:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:orientation="vertical">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/main_view"
android:layout_gravity="left|center_vertical"/>
</LinearLayout>
and here's list_main_view_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
android:minHeight="?android:attr/listPreferredItemHeight"
android:focusable="false"
android:focusableInTouchMode="false">
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Switch"
android:id="#+id/switch1"
android:layout_gravity="center_horizontal|top"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentLeft="true"
android:checked="true"
android:tag="0"/>
</RelativeLayout>
Ok you should add an id to your list view in your XML.
Then you can apply that ID to your ListView in your method:
ListView list = (ListView) findViewById(R.id.my_list_view);
Right now your list reference is pointing at your Linear layout (white space outside your actual ListView). That's why it detects clicks outside the ListView
I think if you set the clickable attribute to false for switch tag in XML like below, it would work.
android:clickable="false"
But, I don't see a point in adding a switch in a list view where switch wouldn't be reacting the way we need it to react to click events. If you replace switch with imageView or TextView it will work as those won't react to click events unless specified.
The only solution I found was to extend ArrayAdapter I used in the code and to override getView
public class MainListAdapter extends ArrayAdapter<String> {
...
Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity) mycontext).getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_main_view_item, null);
assert convertView!=null;
Switch s = (Switch)convertView.findViewById(R.id.switch1);
assert s!=null;
s.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.w("MiniTasker", "adapter w00t " + Integer.toString(view.getId()));
}
});
}
return super.getView(position, convertView, parent);
}
}
android:focusable="false"
android:focusableInTouchMode="false"
Add this in the XML inside the Switch element.

Categories