I'm having troubles getting my head around how to create add animation to a LinearLayout that is translucent. There are two views with opacity and a moving background (Google map if it is of importance). View1 is a LinearLayout and view2 is being added to view1. However when adding view2 it is seen through view1 (see left animation below).
Is there any way I can prevent this to achieve my animation correctly? (goal: see animation on the right) Keep in mind that the background is changing and is not a fixed picture.
Best regards
Rawa
I imagine my comment may not have been entirely clear, so I put together a simple example to better explain and demonstrate. As I'm uncertain as to what your Views will be, I've left them rather generic, and set some hard-coded properties you will want to change.
main.xml layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/stripes_diag" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00000000" >
<TextView android:id="#+id/view2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:background="#88ffffff"
android:textColor="#000000"
android:textSize="40sp"
android:text="Lorem Ipsum" />
</LinearLayout>
<View android:id="#+id/view1"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#88ffffff" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Animate"
android:onClick="onClick" />
</LinearLayout>
</RelativeLayout>
MainActivity class:
public class MainActivity extends Activity
{
View view1, view2;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view1 = findViewById(R.id.view1);
view2 = findViewById(R.id.view2);
}
public void onClick(View v)
{
view2.setY(view2.getHeight());
ObjectAnimator anim = ObjectAnimator.ofFloat(view2, "y", 0);
anim.setDuration(1500);
anim.start();
}
}
A look at the effect:
Related
I have an imageView that I want to move given a specific situation.
Initially I have a Relative layout with two textViews and an imageview. The textViews are oriented with one above the other. The imageView is set
android:layout_below="#id/text_view1"
android:layout_toEndOf="#+id/text_view2".
In the logic text_view2 is removed when a specific condition is met. I want to programmatically move the imageView to the end of text_view1 when this condition is met. Essentially when text_view2 is removed, I want to set the imageView to
android:layout_toEndOf="#+id/text_view1"
I don't believe setting X,Y,Z values is appropriate here because programmatically, I don't know where the imageView will show up given different screen sizes, and densities. I just need it to move to the end of the first textView.
Take a look at RelativeLayout.LayoutParams. You will need to manipulate the layout rules in the layout params as follows:
// Make textView2 invisible
tv2.visibility = View.INVISIBLE
// Get the LayoutParams of the ImageView
val ivParams = iv.layoutParams as RelativeLayout.LayoutParams
// Change the rule to be to the right of textView1
ivParams.addRule(RelativeLayout.RIGHT_OF, tv1.id)
// Since the placement of textView2 is changing, request a layout.
iv.requestLayout()
Consider using "END_OF" instead of "RIGHT_OF".
You can either place the Views in a nested LinearLayout or use a ConstraintLayout with a Barrier.
It is generally recommended to use ConstraintLayout because nested LinearLayouts are bad for performance but since ConstraintLayout takes some getting used to, I did not want to omit the other option.
To demonstrate the two approaches I've set up a small example with a LinearLayout and a ConstraintLayout in the same screen:
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.TabTwoFragment">
<LinearLayout
android:layout_width="240dp"
android:layout_height="128dp"
android:background="#cccccc">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#44ff0000"
android:maxWidth="160dp"
android:text="Upper TextView\nin\n nested\n LinearLayout" />
<TextView
android:id="#+id/longTextViewInLinearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#4400ff00"
android:maxWidth="160dp"
android:text="Lower TextView in nested LinearLayout" />
</LinearLayout>
<ImageView
android:id="#+id/linearLayoutImageView"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="#ffffff"
android:src="#drawable/ic_android_black_24dp"
android:tint="#color/colorPrimary" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="240dp"
android:layout_height="128dp"
android:layout_gravity="bottom|end"
android:background="#666666">
<TextView
android:id="#+id/shortTextViewInConstraintLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#44ff0000"
android:maxWidth="160dp"
android:text="Upper TextView\nin\n nested\nConstraintLayout"
android:textColor="#ffffff"
app:layout_constraintBottom_toTopOf="#+id/longTextViewInConstraintLayout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="#+id/longTextViewInConstraintLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#4400ff00"
android:maxWidth="160dp"
android:text="Lower TextView in ConstraintLayout"
android:textColor="#ffffff"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/shortTextViewInConstraintLayout" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="shortTextViewInConstraintLayout, longTextViewInConstraintLayout" />
<ImageView
android:id="#+id/constraintLayoutImageView"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="#ffffff"
android:importantForAccessibility="no"
android:src="#drawable/ic_android_black_24dp"
android:tint="#color/colorAccent"
app:layout_constraintStart_toEndOf="#+id/barrier"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
If the ImageView is clicked, the longer TextView will disappear and the ImageView will move closer to the short TextView. The animations are provided by Android's transition framework, so basically all you have to do is trigger the transition by calling TransitionManager.beginDelayedTransition()
For demonstration purposes, I've placed all the code in one method. Please note that normally one would have the TransitionSet as field of the Fragment so that it does not have to be recreated every time you need it. (The code is in Java since Android Studio supports automatic translation to Kotlin if required but not the other way round ;-) )
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
TransitionSet ts = new TransitionSet();
ts.addTransition( new ChangeBounds());
ts.addTransition(new Slide());
View imageViewInLinearLayout = view.findViewById(R.id.linearLayoutImageView);
imageViewInLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TransitionManager.beginDelayedTransition((ViewGroup)getView(), ts);
view.findViewById(R.id.longTextViewInLinearLayout).setVisibility(GONE);
}
});
View imageViewInConstraintLayout = view.findViewById(R.id.constraintLayoutImageView);
imageViewInConstraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TransitionManager.beginDelayedTransition((ViewGroup)getView(), ts);
view.findViewById(R.id.longTextViewInConstraintLayout).setVisibility(GONE);
}
});
}
I've a custom button layout: Its a FrameLayout as a background with a normal Button in the center with an icon next to the text.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/framelayout"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="#F00">
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonWithIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="#null"
android:drawableStart="#android:drawable/ic_delete"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#FFF"/>
</FrameLayout>
I had an onClickListeners on the Button and I realized, clicks on the background (=FrameLayout) weren't detected. Because of this I want an onClickListener that detects clicks on the FrameLayout and also on the Button, without having two Listeners, that do the same.
I tried giving the RelativeLayout an ID, but the layout couldn't be found (=null).
Maybe my button layout isn't optimal. But I need a fullwidth button with a icon next to the text, without any spaces between the icon and the text.
The Icons gets set like this
button.setCompoundDrawablesWithIntrinsicBounds(R.mipmap.ic_icon, 0, 0,0);
Thank you
You can just add one OnClickListener to both views. That way, you only write your code once, and if you click either the FrameLayout or the Button that same code will run.
final View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Add Your OnClick Code Here
}
};
framelayout.setOnClickListener(mOnClickListener);
buttonWithIcon.setOnClickListener(mOnClickListener);
You can put all of your views that you want them to be clickable and remove all clickListeners of entire views.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/linearlayout">
<FrameLayout
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="#F00">
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonWithIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="#null"
android:drawableStart="#android:drawable/ic_delete"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#FFF"/>
</FrameLayout>
</LinearLayout>
and add this clickListener to LinearLayout:
LinearLayout linearlayout=(linearLayout)findViewById(R.id.linearlayout);
linearlayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Add Your Code Here
}
});
Create a function in your Activity with a View Argument, and in your layout, set the onClick to your two views.
Activity:
public void myAction(View v){
// Do what you want
}
Your Layout:
<FrameLayout
android:id="#+id/framelayout"
style="?android:attr/buttonStyle"
android:onClick="myAction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="#F00">
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonWithIcon"
android:onClick="myAction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="#null"
android:drawableStart="#android:drawable/ic_delete"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#FFF"/>
</FrameLayout>
Maybe adding in just the FrameLayout may dispatch the event in the button also, i can't test right now :)
I am trying to set focus on a LinearLayout view when returning to an activity from another activity. The scenario:
I have one activity with a bunch of LinearLayout items (with stuff in them), some of which are text, others photos. Let's say the top most of 20 is a TextView and the rest are photos. When I leave this activity (to take a picture), activity goes to the top of the list where the TextView is - no matter what I do.
How do I force the focus back on the item that I was on before the new activity was triggered?
I have already tried this with no success:
[How Linear Layout get Focus?
I am currently trying to force the focus by remembering the previous view without success (though I can see the code being executed). The in my main activity:
#Override
public void onResume() {
super.onResume();
// See if we had a field with focus previously...
if (mPreviousView != null) {
if (mPreviousView.isFocusable()) {
mPreviousView.requestFocus();
}
}
}
...
#Override
protected void onPause() {
super.onPause();
mPreviousView = this.getCurrentFocus();
}
I am dynamically setting the focus in the LinearLayout:
private void initialize() {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.field_photo_picker, this);
// To allow focus to be returned to control after taking photo
this.setFocusableInTouchMode(true);
this.setFocusable(true);
this.setClickable(true);
And finally the XML for the LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<TextView
android:id="#+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="normal"
android:text="" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/photoValue"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="17sp"
android:textStyle="normal"
android:gravity="right|center_vertical"
android:layout_weight="1"
android:layout_marginRight="5dp"
android:text="" />
<ImageButton
android:id="#+id/photoPicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/form_photo"
android:padding ="5dp"
android:gravity="center_vertical"
android:focusableInTouchMode="false"
android:background="?android:attr/selectableItemBackground"
android:layout_weight="0"
/>
</LinearLayout>
<View
android:layout_marginTop="8dp"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/grey" />
</LinearLayout>
</merge>
make your textview and other views focusable, you made this.setFocusable(true); which doesn't make sense
I have a scrollview in my android app that supports overscroll and has a nice bounce effect. What I would like to do is add a view that is initially hidden to the user, but if they scroll up beyond the initial view, then they can see it. How can I do this? Is it possible to do this using just xml?
You can place the initial view and the additional view in a LinearLayout, and when the scroll view is created, you can immediately scroll downwards to the initial view. You can set the initial scroll offset using the xml attribute android:scrollY.
By code you can definitely achieve this. In this sample code I have 15 buttons in srollview. And hide 1st button for initial display.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ScrollView hscrollViewMain = (ScrollView)findViewById(R.id.sview);
hscrollViewMain.post(new Runnable() {
public void run() {
Button bt2 = (Button)findViewById(R.id.button2);
int nY_Pos = bt2.getTop();
// scroll to top of bt2
hscrollViewMain.scrollTo(0,nY_Pos);
}
});
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:id="#+id/bt1"
android:layout_height="wrap_content"
android:text="Button 1" />
<Button
android:id="#+id/button2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button 2" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button 3" />
.
.
.
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button 15" />
</LinearLayout>
</ScrollView>
I'm trying to start an application and I'm kind of lost on how to do what I want.
This is what I want
Both red panels should be able to slide to the sides and the white one should expand if one of them (or both) them is collapsed, occupying that panel space.
When I have the red panels on the screen, the white panel show all the content and not be under any of the panels.
What have I tried so far:
I started by trying with two SlidingDrawers, but the white panel got behind the red ones, so, no luck there.
After that I tried with 2 LinearLayouts (red panels) and a RelativeLayout (white panel), and tried to change width of the layouts with buttons (like is on the image on top). This caused always problems that I didn't know how to resolve.
Suggestions?
Edit:
xml of the SlidingDrawer example:
<LinearLayout
android:id="#+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="bottom"
android:background="#FFFFFFFF">
<SlidingDrawer
android:layout_width="100dip"
android:id="#+id/SlidingDrawer"
android:handle="#+id/slideHandleButton"
android:content="#+id/contentLayout"
android:layout_height="fill_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:id="#+id/contentLayout"
android:orientation="horizontal"
android:background="#C0C0C0"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Meio"
android:layout_toRightOf="#+id/buttonEsq" />
</LinearLayout>
<Button
android:layout_width="30dip"
android:layout_height="30dip"
android:id="#+id/slideHandleButton"
android:background="#drawable/arrowup">
</Button>
</SlidingDrawer>
</LinearLayout>
And the xml of the LinearLayout example:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:layout_toLeftOf="#+id/linearLayout3"
android:layout_toRightOf="#+id/linearLayout1"
android:background="#FFFFFFFF">
<Button
android:id="#+id/buttonEsq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="v--" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Meio"
android:layout_toRightOf="#+id/buttonEsq" />
<Button
android:id="#+id/buttonDir"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/textView1"
android:text="--v" />
</RelativeLayout>
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="50dip"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:background="#FFFF0000">
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Esquerda" />
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout3"
android:layout_width="50dip"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:background="#FFF00000">
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Direita" />
</LinearLayout>
</RelativeLayout>
The android code (the commented part is the code of the 1st example):
public class Main extends Activity {
Button slideHandleButton;
Button slideHandleButtonLeft;
Button slideHandleButtonRight;
SlidingDrawer slidingDrawer;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayouts);
/* slideHandleButton = (Button) findViewById(R.id.slideHandleButton);
slidingDrawer = (SlidingDrawer) findViewById(R.id.SlidingDrawer);
slidingDrawer.setOnDrawerOpenListener(new OnDrawerOpenListener() {
#Override
public void onDrawerOpened() {
slideHandleButton.setBackgroundResource(R.drawable.arrowdown);
}
});
slidingDrawer.setOnDrawerCloseListener(new OnDrawerCloseListener() {
#Override
public void onDrawerClosed() {
slideHandleButton.setBackgroundResource(R.drawable.arrowup);
}
});*/
slideHandleButtonLeft = (Button) findViewById(R.id.buttonEsq);
slideHandleButtonLeft.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
LinearLayout lll = (LinearLayout) findViewById(R.id.linearLayout1);
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(50, LinearLayout.LayoutParams.FILL_PARENT);
lll.setLayoutParams(params);
}
});
}
}
SlidingDrawer can only slide in from the right or the bottom, it is unable to slide in from the top or the left. You can try the answer from this question: Android SlidingDrawer from top? or you can get try rewrite the source code http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/widget/SlidingDrawer.java.
However, a SlidingDrawer wont allow
the white panel show all the content and not be under any of the panels
as it will slide over the white panel
The only solution I can think of is to use a series of scale/translate, translate the left or right panel off-screen and set visibility to gone, while at the same time scale the center panel out in the direction of whichever red panel is being removed.
I tried to make a similar prototype some time ago and used this method but the scale animations looked terrible, not to mention the onAnimationEnd listener doesn't work, you'll have to extend a LinearLayout and override onAnimationEnd there for it to work.