in my Android app i'm defining the following layout which is working fine.
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black">
<com.test.zoom.ImageZoomView
android:id="#+id/zoomview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ZoomControls
android:id="#+id/zoomControls"
android:layout_width="130dp"
android:layout_height="50dp"
android:layout_gravity="bottom|right"/>
</FrameLayout>
But when set the layout parameters on the FrameLayout the ZoomControls are gone.
Do you have a hint what i'm doing wrong?
ViewTreeObserver viewTreeObserver = frame.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
frame.getViewTreeObserver().removeGlobalOnLayoutListener(this);
frame.setLayoutParams(new LinearLayout.LayoutParams(frame.getMeasuredWidth(), frame.getMeasuredWidth()));
}
});
}
Your ZoomControls is a child of FrameLayout. So if you remove the FrameLayout, all of its children(com.test.zoom.ImageZoomView & ZoomControls) will be removed as well.
Try to make your ZoomControl be indepent from FrameLayout, like this:
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black">
<com.test.zoom.ImageZoomView
android:id="#+id/zoomview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
<ZoomControls
android:id="#+id/zoomControls"
android:layout_width="130dp"
android:layout_height="50dp"
android:layout_gravity="bottom|right"/>
Related
I have FrameLayout: Width =match_parent, I want set Height = 70% * Width
Ex:
<FrameLayout
android:id="#+id/fiew"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp">
</FrameLayout>
How can set Height =70% * Width?
Use ConstraintLayout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:background="#android:color/black"
app:layout_constraintDimensionRatio="H,3:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
Here just use ratio in app:layout_constraintDimensionRatio to specify the percentage
You can use a ViewTreeObserver to know when the layout has completed, and then change the layout params of the FrameLayout to adjust the height.
frame_layout.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/fiew"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="#color/colorPrimary"
android:layout_marginTop="20dp">
</FrameLayout>
</LinearLayout>
FrameLayoutActivity
public class FrameLayoutActivity extends AppCompatActivity {
private FrameLayout fiew;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_layout);
fiew = (FrameLayout) findViewById(R.id.fiew);
final View layout = (View)fiew.getParent();
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener (new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int width = layout.getMeasuredWidth();
//int height = layout.getMeasuredHeight();
ViewGroup.LayoutParams params = fiew.getLayoutParams();
params.height = (int) (width * 0.7);
fiew.setLayoutParams(params);
fiew.invalidate();
}
});
}
}
A simple approach is to take that Framelayout inside a Linearlayout and play with weight. No need to use Constraint layout.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="10">
<FrameLayout
android:id="#+id/fiew"
android:layout_width="match_parent"
android:layout_weight="7"
android:layout_height="0dp">
</FrameLayout>
</LinearLayout>
This is what I want to achieve :
I wanted to use AbsoluteLayout but it is deprecated.
So I made a RelativeLayout beneath the blue view in the image above, and then put everything inside a ScrollView, but the hidden view is still 'on' the blue view, and not below it. Also, the screen scrolls, but the hidden part is just cut , and instead I see the my app's default background..
Any ideas?
EDIT :
my current try :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/imageView" />
<LinearLayout
android:id="#+id/centerHolder"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
.....
.....
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_below="#id/main_holder"
android:background="#color/black_color">
</RelativeLayout>
</RelativeLayout>
</ScrollView>
I am taking this from a project of mine which displays a RecyclerView where you can add data if you click on a row - because the click "opens" the bottom sheet.
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rl_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.fragment.BlockFragment">
<include
android:id="#+id/ll_header"
layout="#layout/layout_header_names" />
<include
android:id="#+id/divider_header"
layout="#layout/layout_divider_horizontal"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="#+id/ll_header" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_block"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/divider_footer"
android:layout_below="#+id/divider_header" />
<include
android:id="#+id/divider_footer"
layout="#layout/layout_divider_horizontal"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#767676"
android:layout_above="#+id/ll_footer" />
<include
android:id="#+id/ll_footer"
layout="#layout/layout_footer_score"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<!-- Here comes my bottom sheet.
It is wrapped inside a FrameLayout, because an include cannot
have a behaviour. The included layout is every layout you
can imagine - mine is a RelativeLayout with two EditTexts
for example. The layout_behaviour is the second important line. -->
<FrameLayout
android:id="#+id/container_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#e3e3e3"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<include layout="#layout/layout_bottom_sheet"/>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
For the behaviour itself, you'll need to get the FrameLayout (the View with the app:layout_behavior="android.support.design.widget.BottomSheetBehavior").
private BottomSheetBehavior bottomSheetBehavior;
bottomSheetBehavior = BottomSheetBehavior.from((FrameLayout)findViewById(R.id.container_bottom_sheet);
//for the sheet to "peek":
bottomSheetBehavior.setPeekHeight(200);
//now you can set the states:
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
It is also possible to set a BottomSheetCallback() in which you can get all the state changes and also the slideOffset!
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_DRAGGING:
case BottomSheetBehavior.STATE_EXPANDED:
break;
case BottomSheetBehavior.STATE_COLLAPSED:
default:
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
I think you should just use LinearLayout to wrap the ImageView and other layouts.
Edited the answer based on comments.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/centerHolder"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
.....
.....
</LinearLayout>
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/imageView"
android:layout_alignParentTop="true" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_below="#+id/centerHolder"
android:background="#color/black_color">
</RelativeLayout>
</RelativeLayout>
</ScrollView>
Just replace your ScrollView with NestedScrollView
Example:
<android.support.v4.widget.NestedScrollView
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
I realized you need something like this, just tested it out , just copy two files and see how it works.
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ScrollView;
public class MainActivity extends AppCompatActivity {
LinearLayout movableLL;
boolean mDragLockGained;
float initialTouchPoint;
// int cutoffElevation;
boolean inAnimation;
ScrollView scrollView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = (ScrollView) findViewById(R.id.scrollView);
movableLL = (LinearLayout) findViewById(R.id.mobileLL);
movableLL.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (inAnimation) return true;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDragLockGained = true;
initialTouchPoint = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
performTranslation(event);
initialTouchPoint = event.getRawY();
break;
case MotionEvent.ACTION_UP:
mDragLockGained = false;
performSettlingAnimation();
break;
}
return true;
}
});
}
private void performTranslation(MotionEvent event) {
float newDelta = event.getRawY() - initialTouchPoint;
float currentY = movableLL.getTranslationY();
if (currentY + newDelta > 0) {
movableLL.setTranslationY(currentY + newDelta);
if (scrollView.getTranslationY() + newDelta < 0){
}
scrollView.setTranslationY(scrollView.getTranslationY() + newDelta);
} else {
movableLL.setTranslationY(currentY);
scrollView.setTranslationY(scrollView.getTranslationY());
}
}
final int SETTLE_ANIMATION_DURATION = 300;
private void performSettlingAnimation() {
ObjectAnimator animLl = ObjectAnimator.ofFloat(movableLL, "translationY",
movableLL.getTranslationY(), convertDpToPixels(this, 150));
inAnimation = true;
animLl.setDuration(SETTLE_ANIMATION_DURATION);
animLl.start();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
inAnimation = false;
}
}, SETTLE_ANIMATION_DURATION);//use animationListener here as a best practice and toggle values in
//on animation start and cancel/finish
ObjectAnimator animSv = ObjectAnimator.ofFloat(scrollView, "translationY", scrollView.getTranslationY()
, 0);
animSv.setDuration(SETTLE_ANIMATION_DURATION);
animSv.start();
}
public static int convertDpToPixels(Context context, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()
);
}
}
and the xml......
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Hello There" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Hello Again" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="WhatsUp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="See ya" />
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="#+id/mobileLL"
android:layout_width="match_parent"
android:layout_height="300dp"
android:translationY="150dp"
android:layout_gravity="bottom"
android:background="#android:color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#99ff0000" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#990000ff" />
</LinearLayout>
Please let me know if I missed something.
For this purposes the best way is to use BottomSheet from Design Support Library from my point of view.
<?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1000dp"
android:background="#android:color/white">
<!-- other layout -->
</RelativeLayout>
</RelativeLayout>
</ScrollView>
<FrameLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_peekHeight="120dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<View
android:layout_width="match_parent"
android:layout_height="240dp"
android:background="#android:color/darker_gray" />
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
It also possible to combine it with your own a CoordinatorLayout Behavior to change scroll position for your scroll view, if needed.
I don't know whay when i setting longClickListener to my a view , it is not fire,It is my layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<RelativeLayout
android:layout_width="match_parent"
android:id="#+id/map"
android:layout_below="#+id/toolbar"
android:layout_height="match_parent">
</RelativeLayout>
<TextView
android:layout_margin="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="16"
android:id="#+id/zoom_level"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<RelativeLayout
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:padding="10dp"
android:background="#drawable/zoom_in_bg"
android:layout_above="#+id/zoom_out"
android:src="#drawable/ic_add_black_24dp"
android:layout_width="wrap_content"
android:id="#+id/zoom_in"
android:layout_marginBottom="1dp"
android:layout_height="wrap_content"/>
<ImageView
android:padding="10dp"
android:background="#drawable/zoom_out_bg"
android:id="#+id/zoom_out"
android:layout_alignParentBottom="true"
android:src="#drawable/ic_remove_black_24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</RelativeLayout>
and it is fragment
public class MapFragment extends BaseFragment implements View.OnLongClickListener
{
private View rootView;
private org.mapsforge.android.maps.MapView mapView ;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
rootView = inflater.inflate(R.layout.fragment_navigation, container, false);
mapView = new org.mapsforge.android.maps.MapView(getContext());
mapView.setOnLongClickListener(this);
RelativeLayout relativeLayout = (RelativeLayout) rootView.findViewById(R.id.map);
relativeLayout.addView(mapView, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
return rootView;
}
#Override
public boolean onLongClick(View view)
{
KLog.error("Long Click called");
return true;
}
}
i have tried SetClickable(true) , setLongClickable(true), setFocusable(true) but i cannot solve this problem.what is the solution?
please advise
You can add this code to your class:
mapView.setLongClickable(true);
Or add android:longClickable="true" to xml.
Put android:longClickable="true" in your Relative layout where you want to add onLongClickListener:
<RelativeLayout
android:layout_width="match_parent"
android:id="#+id/map"
android:layout_below="#+id/toolbar"
android:layout_height="match_parent"
android:longClickable="true">
</RelativeLayout>
Try with set long click listener on Relative layout instead of mapView:
RelativeLayout relativeLayout = (RelativeLayout) rootView.findViewById(R.id.map);
relativeLayout.setOnLongClickListener(this);
I have the follwing layout:
<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="vertical" >
<View
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:id="#+id/bottomNav"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Username: " />
</LinearLayout>
Programatically I'm replacing the view "content" with my Fragment:
View view = inflater.inflate(R.layout.kwiz_game, container, false);
contentView = view.findViewById(R.id.content);
currentFragment = new KwizCardBackFragment(android.R.drawable.btn_plus);
getFragmentManager().beginTransaction().replace(R.id.content,
currentFragment);
However the fragment is taking all the space and the Layout with the TextView is not shown.
I also tried to use RelativeLayouts with alignParentBottom=true and other stuff...
View of the Fragment which replaces the content:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background_kwiz_item" >
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:scaleType="centerCrop" />
</RelativeLayout>
OnCreateView of the fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_card_back, container,
false);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
if (drawable != null) {
imageView.setImageDrawable(drawable);
} else {
imageView.setBackgroundResource(drawableId);
}
return view;
}
After hours of debugging I finally found the mistake... Some of my layouts had views with the id "content". I thought when I look for R.id.content that the "nearest" element will be used... that's not the case!
Thanks anyone!
I modified your layout a little bit and this seems to achieve what you want:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:layout_above="#+id/bottomNav" />
<LinearLayout
android:id="#+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Username: " />
</LinearLayout>
</RelativeLayout>
And a small side note, I see you used fill_parent in your layout, but that's deprecated since API level 8, so you should use match_parent instead :)
Hope this helps, cheers!
You should use FrameLayout as your fragment container, and put (and then replace) your fragments into that FrameLayout container.
I've relative layout i.e. main.xml which I set as follows. But now I've to put view1 on view2 with width=200dp and height =100dp, so that view2 will be large one and view1 will be small one on it.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="#+id/MainPanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/panel_bottom"
android:layout_gravity="center_horizontal" >
<com.proj.demo.view1
android:id="#+id/sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignWithParentIfMissing="true"
android:layout_centerInParent="true"
android:layout_toLeftOf="#+id/panel_quick_buttons"
/>
<com.proj.demo.view2
android:id="#+id/sheet2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignWithParentIfMissing="true"
android:layout_centerInParent="true"
android:layout_toLeftOf="#+id/panel_quick_buttons"
/>
</RelativeLayout>
</RelativeLayout>
What do you want to achieve? If you just want to change width and heigh than:
RelativeLayout rl = (RelativeLayout) findViewById(R.id.yourId);
rl.getLayoutParams().height = 100;
rl.getLayoutParams().width = 100;