我想实现这个动画,它是覆盖标签布局的搜索编辑框,我必须告诉我在父布局android:animateLayoutChanges="true"
上尝试了这个代码并将标签布局可见性设置为{{1但它只是动画向上移动的标签,而不是搜索框覆盖标签布局。
答案 0 :(得分:7)
我制作了一个看起来像你的快速虚拟应用程序,并试图实现你在动画中显示的内容。看下面的效果(你可以使它更流畅和优雅):
我做的方式有点棘手。我在这里发布了我的整个代码:
的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pabhinav.testapp3">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<小时/> MainActivity.java
package com.pabhinav.testapp3;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.LinearInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import static com.pabhinav.testapp3.R.id.container;
public class MainActivity extends AppCompatActivity implements PlaceholderFragment.OnSearchBoxClick{
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
/**
* Search Box in activity.
*/
private RelativeLayout dummySearchBox;
private LinearLayout topSearchBox;
/**
* Overlay View appears when search box is clicked.
*/
private View overlay;
/**
* Back button image view for top search box
*/
private ImageView backButtonSearchBox;
/**
* PlaceHolderFragment saved only for second tab,
* which has search box.
*/
private PlaceholderFragment placeholderFragment;
private float xDelta, yDelta;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
overlay = findViewById(R.id.overlay_whole_page);
backButtonSearchBox = (ImageView)findViewById(R.id.search_icon);
// Consume touch event, so that it does not pass to parent views.
// This is done to block swipe events of tab layout, once search
// box is clicked.
overlay.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
// TabLayout and ViewPager.
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
mViewPager = (ViewPager) findViewById(container);
dummySearchBox = (RelativeLayout)findViewById(R.id.dummy_search_box);
topSearchBox = (LinearLayout)findViewById(R.id.top_search_box);
// Set up the ViewPager with the sections adapter.
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
@Override
public void onPageSelected(int position) {
for (int i = 0; i < tabLayout.getTabCount(); i++) {
if(i == position){
tabLayout.getTabAt(i).setIcon(getTabIconHighlighted(i));
} else {
tabLayout.getTabAt(i).setIcon(getTabIconUnhighlighted(i));
}
}
}
@Override
public void onPageScrollStateChanged(int state) {}
});
// Setup viewpager with tablayout and also set up icons of each tabs :
tabLayout.setupWithViewPager(mViewPager);
for(int i = 0; i<tabLayout.getTabCount(); i++){
// Set first tab highlighted :
if(i == 0){
tabLayout.getTabAt(i).setIcon(getTabIconHighlighted(i));
} else {
tabLayout.getTabAt(i).setIcon(getTabIconUnhighlighted(i));
}
}
// Back Button in top search box clicked.
backButtonSearchBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
overlay.setVisibility(View.INVISIBLE);
dummySearchBox.setVisibility(View.VISIBLE);
topSearchBox.setVisibility(View.INVISIBLE);
AnimationSet animSet = new AnimationSet(true);
animSet.setFillAfter(false);
animSet.setDuration(150);
animSet.setInterpolator(new LinearInterpolator());
TranslateAnimation translate = new TranslateAnimation(-xDelta, 0, -yDelta, 0);
animSet.addAnimation(translate);
ScaleAnimation scale = new ScaleAnimation(1.2f, 1f, 1.2f, 1f);
animSet.addAnimation(scale);
dummySearchBox.startAnimation(animSet);
animSet.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
placeholderFragment.showSearchLayout();
dummySearchBox.setVisibility(View.INVISIBLE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
});
}
private int getTabIconUnhighlighted(int position){
switch (position){
case 0 : return R.drawable.ic_home_black_24dp;
case 1 : return R.drawable.ic_search_black_24dp;
case 2 : return R.drawable.ic_heart_black_24dp;
case 3 : return R.drawable.ic_view_headline_black_24dp;
}
return -1;
}
private int getTabIconHighlighted(int position){
switch(position){
case 0 : return R.drawable.ic_home_highlighted_24dp;
case 1 : return R.drawable.ic_search_highlighted_24dp;
case 2 : return R.drawable.ic_heart_highlighted_24dp;
case 3 : return R.drawable.ic_view_headline_highlighted_24dp;
}
return -1;
}
/**
* This event is when search box from fragment is clicked,
* need to animate the search box present in activity
* to reach the top of activity display.
*/
@Override
public void onClick() {
dummySearchBox.setVisibility(View.VISIBLE);
dummySearchBox.clearFocus();
((EditText)findViewById(R.id.search_edit_text)).clearFocus();
performAnimation(dummySearchBox);
}
public void performAnimation(final RelativeLayout dummySearchBox){
if(xDelta == 0 && yDelta == 0){
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int[] originalPos = new int[2];
dummySearchBox.getLocationOnScreen(originalPos);
xDelta = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18, getResources().getDisplayMetrics());
yDelta = originalPos[1] - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics());;
}
AnimationSet animSet = new AnimationSet(true);
animSet.setFillAfter(false);
animSet.setDuration(200);
animSet.setInterpolator(new LinearInterpolator());
TranslateAnimation translate = new TranslateAnimation( 0, -1*xDelta, 0, -1*yDelta);
animSet.addAnimation(translate);
ScaleAnimation scale = new ScaleAnimation(1f, 1.15f, 1f, 1.15f);
animSet.addAnimation(scale);
dummySearchBox.startAnimation(animSet);
animSet.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
topSearchBox.setVisibility(View.VISIBLE);
dummySearchBox.setVisibility(View.INVISIBLE);
overlay.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public static final String ARG_SECTION_NUMBER = "section_number";
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment.
PlaceholderFragment placeholderFragment = new PlaceholderFragment();
placeholderFragment.setOnSearchBoxClick(MainActivity.this);
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, position + 1);
placeholderFragment.setArguments(args);
if(position == 1){
MainActivity.this.placeholderFragment = placeholderFragment;
}
return placeholderFragment;
}
@Override
public int getCount() {
// Show 4 total pages.
return 4;
}
}
}
PlaceholderFragment.java
package com.pabhinav.testapp3;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* @author pabhinav
*/
public class PlaceholderFragment extends Fragment {
private LinearLayout searchLayout;
public PlaceholderFragment() {
}
private OnSearchBoxClick onSearchBoxClick;
public void setOnSearchBoxClick(OnSearchBoxClick onSearchBoxClick){
this.onSearchBoxClick = onSearchBoxClick;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
int sectionNumber = getArguments().getInt(MainActivity.SectionsPagerAdapter.ARG_SECTION_NUMBER);
View rootView = inflater.inflate((sectionNumber == 2) ? R.layout.fragment_search : R.layout.fragment_main, container, false);
if(sectionNumber != 2) {
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, sectionNumber));
} else {
// Its the fragment with search box :
TextView searchText = (TextView) rootView.findViewById(R.id.search_text);
ImageView searchIcon = (ImageView)rootView.findViewById(R.id.search_icon);
searchLayout = (LinearLayout)rootView.findViewById(R.id.search_linear_layout);
// Need to do transition when clicked on any of the search box elements :
View.OnClickListener clickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
searchLayout.setVisibility(View.INVISIBLE);
if(onSearchBoxClick != null)
onSearchBoxClick.onClick();
}
};
searchText.setOnClickListener(clickListener);
searchLayout.setOnClickListener(clickListener);
searchIcon.setOnClickListener(clickListener);
}
return rootView;
}
public void showSearchLayout(){
searchLayout.setVisibility(View.VISIBLE);
}
public interface OnSearchBoxClick{
public void onClick();
}
}
<小时/> activity_main.xml中
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.pabhinav.testapp3.MainActivity">
<android.support.design.widget.TabLayout
android:layout_marginTop="8dp"
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Top Search Box -->
<!-- Only appears when search box is clicked -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:id="@+id/top_search_box"
android:visibility="invisible"
android:orientation="horizontal">
<RelativeLayout
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<ImageView
android:gravity = "center"
android:layout_width="52dp"
android:paddingLeft="24dp"
android:paddingRight="8dp"
android:id="@+id/search_icon"
android:layout_height="match_parent"
android:src="@drawable/ic_arrow_back_black_24dp"/>
<EditText
android:layout_toEndOf="@+id/search_icon"
android:hint="@string/search_soundcloud"
android:textSize="18sp"
android:background="@android:color/transparent"
android:textColorHint="#B3B3B3"
android:layout_margin="4dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</LinearLayout>
<!-- Dummy container for search box -->
<!-- This will do transition from its location to top_search_box location -->
<RelativeLayout
android:id="@+id/dummy_search_box"
android:layout_width="match_parent"
android:layout_below="@+id/tabs"
android:visibility="invisible"
android:layout_height="wrap_content"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:id="@+id/search_linear_layout_dummy"
android:orientation="horizontal">
<RelativeLayout
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:background="@android:color/white"
android:elevation="2dp"
android:translationZ="2dp">
<ImageView
android:gravity = "center"
android:layout_width="20dp"
android:layout_marginStart="16dp"
android:id="@+id/search_icon_dummy"
android:layout_height="match_parent"
android:src="@drawable/ic_search_light_black_24dp"/>
<EditText
android:id="@+id/search_edit_text"
android:layout_toEndOf="@+id/search_icon_dummy"
android:hint="@string/search_soundcloud"
android:textSize="16sp"
android:background="@android:color/transparent"
android:textColorHint="#B3B3B3"
android:layout_margin="4dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
<android.support.v4.view.ViewPager
android:layout_below="@+id/tabs"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Dummy overlay over whole page, More things can be added like listview
which displays result of searched text -->
<View
android:id="@+id/overlay_whole_page"
android:layout_below="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:background="#72000000" />
<!-- Dummy shadow below tablayout -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/tabs"
android:background="#42000000" />
</RelativeLayout>
fragment_search.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: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="com.pabhinav.testapp3.MainActivity$PlaceholderFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:id="@+id/search_linear_layout"
android:orientation="horizontal">
<RelativeLayout
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:background="@android:color/white"
android:elevation="2dp"
android:translationZ="2dp">
<ImageView
android:gravity = "center"
android:layout_width="20dp"
android:layout_marginStart="16dp"
android:id="@+id/search_icon"
android:layout_height="match_parent"
android:src="@drawable/ic_search_light_black_24dp"/>
<TextView
android:id="@+id/search_text"
android:layout_toEndOf="@+id/search_icon"
android:text="@string/search_soundcloud"
android:gravity="center_vertical"
android:textColor="#B3B3B3"
android:textSize="16sp"
android:layout_margin="4dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</LinearLayout>
<TextView
android:id="@+id/suggested_stations"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="56dp"
android:textSize="18sp"
android:layout_below="@+id/search_linear_layout"
android:text = "@string/suggested_stations"/>
<LinearLayout
android:layout_below="@+id/suggested_stations"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="0dp"
android:layout_height="240dp"
android:src="@drawable/image_1"
android:layout_weight="1"/>
<ImageView
android:layout_marginStart="16dp"
android:layout_width="0dp"
android:layout_height="240dp"
android:src="@drawable/image_2"
android:layout_weight="1"/>
</LinearLayout>
</RelativeLayout>
<小时/> 从这里下载整个项目:https://drive.google.com/file/d/0B_Mi44NWLWmyNFNkeHJ6cVBLTTg/view?usp=sharing
希望它有所帮助!