Android: Click outside of a listview in a listfragment - java

I have a listview which occupies all the space of the layout IN THEORY, but actually it occupies only half of the layout because it has got only 5 elements and it doesn't cover all the screen. I'd like to know when I touch OUTSIDE of the listview. I tried to create a clicklistener method for the layout of the listfragment which contains the list, but it is never used because IN THEORY the listview occupies all the layout, so the click isn't found. It is the same for the layout of the activity more or less. In that case the click is found only on the edges, so I can't find a method to solve my problem.
Here is the fragment layout:
<LinearLayout 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="#android:id/list" />
Here is the activity layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
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="com.example.utente.actionbar.MainActivity">
<Button
android:text="MULTI"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="26dp"
android:id="#+id/button" />
<Button
android:text="SINGOLO"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/button"
android:layout_alignLeft="#+id/button"
android:layout_alignStart="#+id/button"
android:layout_marginBottom="25dp"
android:id="#+id/button2" />

IN THEORY the listview occupies all the layout
Not a theory, that is exactly what happens; by using android:layout_height="match_parent" the View will always take the full screen height.
listView.setOnClickListener would work if you want to see if you clicked anywhere in the ListView, but you typically would instead want listView.setOnItemClickListener to see if you have clicked on any single item, and not the entire list.
Refer: difference between onClickListener and onItemClickListener
If you really want to shrink the ListView, then android:layout_height="wrap_content" is an option, but I'm not sure that works without content actually being loaded into that View since the content wrapping is applied at inflation-time, which since it has no adapter set, can't be done.
If you are needing to detect a listener literally "outside the ListView", then you need to set some type of click / touch listener on the rootView of that Fragment.
public View onCreateView(...) {
rootView = inflater.inflate(...);
listView = ...;
listView.setOnTouchListner(...
#Override
public boolean onTouch(View v, MotionEvent event) {
return false; // Says that click was not handled here.
}
});
rootView.setOnTouchListner(...
// TODO: Check if click landed outside the ListView
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() != android.R.id.listView) { // Not the list
if (event.getAction() == MotionEvent.ACTION_UP) {
// Up action more reliable than "down"
return true;
}
}
}
);
return rootView;
}

<LinearLayout 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="wrap_content" <!-- Or specific height -->
android:id="#android:id/list" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/clickView" />
</LinearLayout>
In Fragmet
public View onCreateView(...) {
rootView = inflater.inflate(...);
View clickView = rootView.findViewById(...);
clickView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do something here
}
});
return rootView;
}
I guess this solves your problem.

Related

Views are not reflecting any changes whatsoever, when done programmatically

The basic view hierarchy is this:
secondActivity
linearLayout(LinearLayout)
constLayout(ConstraintLayout)
textbox(TextView)
image(ImageView)
image2
image3
...
The textbox TextView has visibility GONE, and goal is to make it VISIBLE on clicking other visible siblings, change some colors and text, and when clicked again it must be invisible again and reverse all changes.
Cant understand whatever it is that am missing. I have checked many older projects in which I did the same thing and cant find any visible differences as to why this code is not working now.
secondActivity.java
public class secondActivity extends Activity {
public boolean isTextBoxHidden;
public ConstraintLayout constLayout;
public TextView textbox;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
constLayout = findViewById(R.id.constLayout);
textbox = findViewById(R.id.textbox);
isTextBoxHidden = false;
// SETTING UP LISTENER
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!isTextBoxHidden) {
constLayout.setBackgroundColor(Color.BLACK); //setting color on previously
v.setBackgroundColor(Color.BLACK); //setting color on visible view
textbox.setText("whatever");
textbox.setVisibility(View.VISIBLE); //was gone
isTextBoxHidden = true;
}
else {
textbox.setVisibility(View.GONE); //hide again
constLayout.setBackgroundColor(Color.WHITE);
v.setBackgroundColor(Color.WHITE);
isTextBoxHidden = false;
}
}
};
// INSERTING LISTENERS into all children
for(int i=0; i<constLayout.getChildCount(); i++) {
constLayout.getChildAt(i).setOnClickListener(clickListener);
}
}
}
activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".secondActivity">
<android.support.constraint.ConstraintLayout
android:id="#+id/constLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
<TextView
android:id="#+id/textbox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="example"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageButton
android:id="#+id/image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#drawable/example"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<!--few more clones of the first imageButton-->
</android.support.constraint.ConstraintLayout>
</LinearLayout>
I can't see where you're setting textbox reference, so maybe that's a clue.
Edit:
Did compiled that example you have provided and everything works correctly, but i assume that [...] gone again for good meant you probably want this to be one shot action so instead of boolean just use Boolean and compare it to null.
Edit:
On the second thought you can just remove isTextBoxHidden = false; in else branch

How do I hide or show layout elements when an Android Activity goes out of focus?

I am trying to hide certain elements in a layout when Android goes out of focus, such that when viewed in the "View recent applications" display, the layout elements will not be visible. Upon selecting the application and going into focus, these elements will be visible again.
My implementation below attempts to show the "content" layout when the application is in focus, and show the "overlay" layout when out of focus, via onWindowFocusChanged().
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is the content page"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is the overlay"/>
</RelativeLayout>
</FrameLayout>
MainActivity.java
public class MainActivity extends ActionBarActivity {
FrameLayout layoutContainer;
RelativeLayout layoutContent;
RelativeLayout layoutOverlay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layoutContainer = (FrameLayout) findViewById(R.id.container);
layoutContent = (RelativeLayout) findViewById(R.id.content);
layoutOverlay = (RelativeLayout) findViewById(R.id.overlay);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
layoutContent.setVisibility(View.VISIBLE);
layoutOverlay.setVisibility(View.GONE);
} else {
layoutOverlay.setVisibility(View.VISIBLE);
layoutContent.setVisibility(View.GONE);
}
}
}
enter code here
However, my implementation does not work. Anyone with any suggestion as to solve this? Thanks!
If you want to hide views in your layout in recent apps try like this
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,WindowManager.LayoutParams.FLAG_SECURE);

Android ListView setOnItemClickListener not working

I am trying to make a ListView with TextViews, I want each textview to be able to be clicked and based on it's position a Fragment is pulled up. However, the itemOnClickListener seems to not even be called.
mDrawerList = (ListView) findViewById(R.id.devices_drawer);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, drawerInfo));
mDrawerList.setItemsCanFocus(false);
mDrawerList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
final int pos, long id) {
Log.d(TAG, "CLICKED " + pos);
selectDevice(pos);
}
});
here's the xml for the list item:
<?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" >
<TextView
android:id="#+id/deviceText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
List view xml file:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/devices_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.DrawerLayout>
It's your whole xml drawer (I presume you try to do a navigation drawer) ? If you have a parent layout check the android:descendantFocusability="blocksDescendants" otherwise you have to wrap your textview in a layout (LinearLayout is sufficient if you don't have a complex UI for the item).
The new OnItemClickListener is an AdapterView.OnItemClickListerner?
(An excellent how-to http://www.vogella.com/articles/AndroidActionBar/article.html#actionbar_navigation_drawer )
Is there a reason you are using mDrawerList.setItemsCanFocus(false);? You don't have any focusable items in your item layout, so it's safe to remove that call. Should work ok after that.
Also check if you are using Button in list row item, it'll over-ride you list item click event
For list items inside your list.. you have to set the attributes below
android:focusable="false"
android:focusableInTouchMode="false"

ListView inside ScrollView which is also inside a Scrollview

I have a Listview inside a Scrollview and manually binding its data on the code behind. My main problem is, when I bind my data, my listview isn't expanding its height. I've tried setting it to wrap_content, fill_parent but nothing works. Here is my XML
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parentScrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RelativeLayout
>
<LinearLayout >
<ImageView
/>
<LinearLayout
>
<TextView />
<TextView />
<LinearLayout >
<TextView/>
<TextView/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView/>
<TextView />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<View />
<TextView/>
<ScrollView
android:id="#+id/childScrollView"
android:layout_width="match_parent"
android:layout_height="375dp"
android:layout_below="#+id/view1"
android:layout_centerHorizontal="true"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginTop="18dp"
android:background="#drawable/scrollviewborder"
android:scrollbarStyle="insideInset" >
<ListView
android:id="#+id/listFriends"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip"
android:paddingLeft="2dip"
android:paddingRight="2dip"
android:paddingTop="2dip"
>
</ListView>
</ScrollView>
<Button />
</RelativeLayout>
</ScrollView>
Please see that it is a nested ListView and here is my code behind
ArrayList<HashMap<String, String>> friendList = new ArrayList<HashMap<String, String>>();
// adding database values to HashMap key => value
for (int i = 0; i < friendName.length; i++) {
// creating new HashMap
HashMap<String, String> friend = new HashMap<String, String>();
//merchant.put(KEY_ID, merchantIdArray[i]);
friend.put(KEY_FRIEND_NAME, friendName[i]);
friend.put(KEY_THUMB_URL,imageIDs[i]);
friendList.add(friend);
}
list=(ListView)findViewById(R.id.listFriends);
adapter =new LazyAdapter(this, friendList);
list.setAdapter(adapter);
What seems to be the problem?
EDIT
Ive added this code for validating which scroll should be used
parentScrollView= (ScrollView) findViewById(R.id.parentScrollview);
parentScrollView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
//Log.v(TAG,"PARENT TOUCH");
findViewById(R.id.childScrollView).getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
});
childScrollView= (ScrollView) findViewById(R.id.childScrollView);
childScrollView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
//Log.v(TAG,"PARENT TOUCH");
findViewById(R.id.childScrollView).getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
The main reason about this is that I will put my Facebook friendlist inside this Listview that it should be scrollable
The problem is the following (as stated here by Romain Guy):
Using a ListView to make it not scroll is extremely expensive and goes
against the whole purpose of ListView. You should NOT do this. Just
use a LinearLayout instead.
#Androyd Friend its always better if u dont put listview inside scrollView and also not scrollview inside listview,
abd then make listview fill parent or fix some hieght in dps like 300dp or that much height u want...

OnItemClickListener consumes onClickListener events

I have read about problems that onClickListener will consume onItemClickListener Events like here or here. My Problem is exactly the other way:
I have a CustomAdapter extends ArrayAdapter where I place model Objects to generate a row. In My Activity i registered an onItemClickListener like so
//items can focus false to try to get the onItemClick-event
mListView.setItemsCanFocus(false);
mListView.setOnItemClickListener(this);
mListView.setAdapter(this.favoritePointAdapter);
then in my Adapter.getView() Method I inflate my layout get my ImageView and register an OnClickListener on it like this
#Override
public View getView(int position, View convertView, ViewGroup parent){
//....inflate other Views.....
LinearLayout clickArea = (LinearLayout)convertView.findViewById(R.id.list_row_favorite_point_click_area);
clickArea.setOnClickListener(this);
//... other logic follows ...
}
at least i Try to fetch this Events in my Adapter like this
#Override
public void onClick(View v) {
Log.d("ListAdapter", "onClick triggered");
//never triggered
switch (v.getId()) {
case R.id.list_row_favorite_point_click_area:
Log.d("ListAdapter", "onClick id->list_row_favorite_point_click_area");
//never triggered
break;
default:
break;
}
}
If you find xml of RowView interesting, here it is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_row_relative_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:focusable="false">
<LinearLayout
android:id="#+id/list_row_icon"
android:layout_width="30dip"
android:layout_height="30dip"
android:layout_gravity="center_vertical"
android:layout_margin="3dip"
/>
<LinearLayout
android:layout_weight="50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="#+id/list_row_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#333333"
android:text="defaultText"
android:textStyle="bold" />
<TextView
android:id="#+id/list_row_region"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#999999"
android:textStyle="italic"
android:text="Region" />
</LinearLayout>
<LinearLayout
android:id="#+id/list_row_favorite_point_click_area"
android:layout_width="50dip"
android:layout_height="50dip">
<ImageView
android:id="#+id/list_row_favorite_icon"
android:layout_width="20dip"
android:layout_height="20dip"
android:layout_gravity="center_vertical"
android:layout_weight="0.1">
</ImageView>
</LinearLayout>
</LinearLayout>
As I said, The ListView's onItemClick of My Activity gets triggered while I never reach onClick inside my Adapter. I think that onItemClick 'feels' responsible for the whole row and consumes TouchEvents. What can I do to work around it?
Note: I tried setItemsCanFocus(false) and focusable in my root to false, too, as mentioned in the other questions.
Rather than using an onClickListener, I'd suggest using the onTouchListener.
Check out this tutorial, which I have used before to get the "swipe screens" in an application:
http://www.warriorpoint.com/blog/2009/05/29/android-switching-screens-by-dragging-over-the-touch-screen/
Also, see the android dev docs on the onTouchListener:
http://developer.android.com/reference/android/view/View.OnTouchListener.html

Categories

Resources