android UI - wrap_content for viewpager - android-layout

I have linear layout with viewpager on top and another vew (button in this example) bottom. Views in the pager have different heights. I would like the pager to have wrap_content height on all pages and button view to fill the rest of the screen.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="New Button"
android:id="#+id/button3"
android:layout_weight="1"/>
</LinearLayout>
This doesn't work. If I give layout_weight=1 to both pager and button, they share screen 50:50 no matter of content height. I tried to call requestLayout() in ViewPager.OnPageChangeListener.onPageSelected() but it doesn't help. Also tried this

Have you tried setting the layout_weight=1 for the pager and the layout_weight=2 for the button?

This works for me, but I don't consider it perfect.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View titlestrip = getChildAt(0);
int h = titlestrip.getMeasuredHeight();
View fv = ((FragmentPagerAdapter)getAdapter()).getItem(getCurrentItem()).getView();
if (fv != null) {
fv.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
h += fv.getMeasuredHeight();
}
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
}
It relies on the fact that my FragmentPagerAdapter.getItem() doesn't instantiate new fragments but return it from container.

Related

How to define setOnClickListner in a popup view(Android Studio)?

So, I have made a button which on clicking opens a popup window with two buttons inside it, but now I am not able to assign setOnClickListner to those two buttons inside the OnCreateMethod as I did for all the other buttons in the main window (If I do then the app Stops responding) as till that time the buttons are not actually there(I think, that's the reason), So could you please help me assign on click listner to those buttons.
Here is the code for the popupWindow excution:
public void onButtonShowPopupWindowClick(View view) {
// inflate the layout of the popup window
LayoutInflater inflater = (LayoutInflater)
getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = inflater.inflate(R.layout.confirm_number_popup, null);
hideSoftKeyboard(Register.this);
// create the popup window
int width = LinearLayout.LayoutParams.WRAP_CONTENT;
int height = LinearLayout.LayoutParams.WRAP_CONTENT;
boolean focusable = true; // lets taps outside the popup also dismiss it
final PopupWindow popupWindow = new PopupWindow(popupView, width, height, false);
// show the popup window
// which view you pass in doesn't matter, it is only used for the window token
popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
// dismiss the popup window when touched
popupView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
popupWindow.dismiss();
return true;
}
});
}
Here is the layout file for the popup view:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:background="#color/white">
<Button
android:id="#+id/btn_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/green_shade_1"
android:text="#string/edit"
android:textSize="16sp"
android:layout_below="#id/txt_edit"
android:layout_alignParentStart="true"
android:layout_marginStart="20dp"
android:background="#color/white"
style="?android:attr/borderlessButtonStyle"/>
<Button
android:id="#+id/btn_Ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/green_shade_1"
android:text="#string/ok"
android:textSize="16sp"
android:layout_below="#id/txt_edit"
android:layout_alignParentEnd="true"
android:layout_marginEnd="20dp"
android:background="#color/white"
style="?android:attr/borderlessButtonStyle"/>
</RelativeLayout>
Please tell me if you are not able to understand the question or if any else code is needed.
Thank You!
Edit: I have already tried adding this in my OnCreate but it doesen't work:
Button btnEdit = findViewById(R.id.btn_edit);
btnEdit.setOnClickListener(v -> {
//The function
});
use
Button btn1 = popupView.findViewById(R.id.btn_edit);
btn1.setOnClickListener{}

RecyclerView with Adapter does not keep values stored in Android

I have the following simple recyclerview layout:
<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:orientation="vertical"
tools:context=".SurvivorPicksheetActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
This recycler view links to the detailed layout of the list items as such:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout 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/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/background"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_centerHorizontal="true"
app:srcCompat="#drawable/gamefield_background" />
<ImageView
android:id="#+id/away"
android:layout_width="160dp"
android:layout_height="150dp"
android:layout_gravity="top|left"/>
<ImageView
android:id="#+id/home"
android:layout_width="160dp"
android:layout_height="150dp"
android:layout_gravity="top|right"
android:scaleX="-1"/>
</androidx.cardview.widget.CardView>
</FrameLayout>
</LinearLayout>
Inside my Adapter java class I have an setOnClickListener for the two ImageView items.
If a user clicks on them the item is selected while the old item is unselected.
The problem I am encountering if that lets say the list of items has 25 items. If I click on the lets say 3rd item, everything works as expected.
Then I scroll to the end of the list, and scroll back up to the top, the selection is not longer valid even thought I clicked/selected prior to scrolling to the end of the list.
I can reclick and item at the top, scroll down and scroll back up and my selection is gone!?
Does anyone know why this is happening and more importantly how i can resolve it!?
UPDATE:
The following is my Adapter class:
public class GameAdapter extends
RecyclerView.Adapter<GameAdapter.GameViewHolder> {
// variable that holds the selected team
private String selectedTeam = "";
#Override
public void onBindViewHolder(GameViewHolder holder, int position) {
final Games game = gameList.get(position);
holder.awayTeamImageView.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
if (selectedTeam.equals(String.valueOf(game.getHomeId()))) {
// RESET PLAYER SELECTION
selectedTeam = "";
selectedGame = "";
} else {
// SET PLAYER SELECTION
selectedTeam = String.valueOf(game.getHomeId());
selectedGame = String.valueOf(game.getKey());
}
}
}
}
class GameViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public GameViewHolder(#NonNull View itemView) {
super(itemView);
itemView.setOnClickListener(this);
awayImageView = itemView.findViewById(R.id.away);
homeImageView = itemView.findViewById(R.id.home);
homeImageView.setOnClickListener(this);
awayImageView.setOnClickListener(this);
}
}
Based on my code above, I 'think' I am setting and unsetting the selected team so that when I scroll to the end and back to the top the selected team should remain vs being recycled and not displaying anymore?!
That's because the old Views are being recycled, back to the initial state. And this is a natutral behavior of RecyclerView.
In order to make each item View "memorize" its check/select state, you need to create a field in your model class to record the state, like isChecked or isSelected.
You can use own domain ViewHolder and ViewModel for recycleview.
Android developer documents gives basic understanding of how to create dynamic RecycleView in below link.
https://developer.android.com/guide/topics/ui/layout/recyclerview
This is expected as the views are recycled and lose their values accordingly whenever you scroll up/down the list; further for configuration changes (like screen rotation) the selected views will be lost.
To fix this, you should go for ViewModel to have persistent data even for configuration changes.
But, as a rescuer, assuming the adapter provided list of games gameList is in a persistent storage like mentioned above; then you can:
Create a selection boolean in the Games model class with getter/setter which has a false initially.
When a row is selected from the RecyclerView, then set the boolean to true like gameList.get(selectedPosition).setIsSelected(true)
Then notifyItemChanged() of that position.

Android Floating Action Button Behaviour with Adview

I'm sorry if this has been already answered but it's been a while and I'm still searching. Since the FAB has a behaviour class you can assign to it which will work with scrolling inside a coordinator layout, I was wondering if it was possible to include behaviour to make the FAB automatically get placed above an adview when it is visible similar to how it reacts to a snack bar. Thank you in advance.
Work Around!
I figured out a work around as I was just playing around some time back, even forgot about the question. Instead of putting my adview inside a container with the rest of my views I simply had to wrap the coordinator view in a Relative layout and set the coordinator layout above the adview ID. I'm sure this might not be the best way to do it.
So what I ended up having is this: NB My adview is set to visibility gone by default and I only set the visibility when the adrequest is complete
<RelativeLayout
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:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:layout_above="#+id/ad_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:visibility="gone"
app:layout_behavior="utils.FabBehavior_Main"
app:rippleColor="#color/fab_ripple"
app:srcCompat="#drawable/ic_fab" />
</android.support.design.widget.CoordinatorLayout>
<com.google.android.gms.ads.AdView
android:id="#+id/ad_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone"
app:adSize="SMART_BANNER"
app:adUnitId="#string/banner_ad_unit_id"
/>
</RelativeLayout>
The utils.FabBehavior_Main is the relative package class that contains the behaviour properties for the view, utils being the package. So in your own application you could have the name space com.myapp.utils.ScrollAwareFab which would have be like this:
public class ScrollAwareFab extends FloatingActionButton.Behavior {
public ScrollAwareFab(Context context, AttributeSet attrs) {
super();
}
#Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target,
nestedScrollAxes);
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
dyUnconsumed);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
/**
* Called when a FloatingActionButton has been hidden
*
* #param fab the FloatingActionButton that was hidden.
*/
#Override
public void onHidden(FloatingActionButton fab) {
super.onShown(fab);
fab.setVisibility(View.INVISIBLE);
}
});
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
child.show();
}
}
}

Receive a long press/click on a linear layout in android?

I'm painfully new to android and I've run into a wall.
I'm trying get a linear layout to function more like a button, with different actions for press and long press - The reason being so I can have 2 differently formatted text labels on each "button". Something along the lines of:
-------------------------
| 2nd | <- Label for long press (regular/smaller type)
| = | <- Label for regular press (bold/larger type)
-------------------------
The posts I've found explain how to receive a regular click on a linear layout (I use the onClick attribute in the layout XML). But I've had no luck with long press. I've tried to define a new onLongClick attribute for xml as described in Aleksander Gralak's answer here: Long press definition at XML layout, like android:onClick does . But had no such luck - it looks like it was intended for a text view, I tried changing it to linear layout but failed miserably.
Here is the object in question: Main.xml
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:background="#drawable/darkgrey_button"
android:onClick="equals" android:longClickable="true" android:id="equalsbutton"
android:focusableInTouchMode="false">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2nd"
android:id="#+id/textView"
android:duplicateParentState="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" = "
android:id="#+id/textView1"
android:duplicateParentState="true"/>
</LinearLayout>
And Main.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void equals(View view) {
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
Add an id to your layout.
<LinearLayout
android:id="#+id/my_button_layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
… >
In your Main.java
Get a reference to your LinearLayout and set a OnLongClickListener.
LinearLayout buttonLayout = (LinearLayout) findViewById(R.id.my_button_layout);
…
buttonLayout.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(Main.this, "Long click!", Toast.LENGTH_SHORT).show();
return true;
}
});

How to draw on perticulr child layout in layout hierarchy in android

I am new to android. I had declare layout hierarchy in main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout class="com.android.MyLayout"
android:id="#+id/mylayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<LinearLayout
android:id="#+id/widget36"
android:layout_width="fill_parent"
android:layout_height="42dp"
android:background="#color/darkgray"
android:orientation="horizontal"
>
</LinearLayout>
<LinearLayout
android:id="#+id/widget38"
android:layout_width="fill_parent"
android:layout_height="390dp"
android:background="#color/black"
android:orientation="horizontal"
>
</LinearLayout>
</LinearLayout>
I also use this layout in my java class
class MyLayout extends LinearLayout
{
public MyLayout(Main context)
{
super(context);
}
public MyLayout(Context context,AttributeSet attribute)
{
super(context,attribute);
}
protected void onLayout (boolean changed, int l, int t, int r, int b)
{
super.onLayout(changed,l,t,r,b);
}
}
Now the problem is that I want to perform draw operation using Canvas on one of the child Layout eg. Layout of id "widget38". How can I proceed ?
Put the views inside the bigger ones. You have to define them in a nested way, not sequentially, closing the parent layout after having defined the child layouts.

Resources