Я пытаюсь реализовать увеличение параллакса, когда пользователь растягивает экран вниз, он должен увеличивать изображение заголовка, но это не работает. Может ли кто-нибудь помочь мне с правильным решением. Это изображение может продемонстрировать, что я хочу получить желаемый результат.
Это моя 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.es.bws.views.activities.MealPlanDetailActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:elevation="6dp"
android:theme="@style/AppTheme.AppBarOverlay">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:contentScrim="@android:color/transparent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/tab_background"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="220dp">
<ImageView
app:layout_collapseMode="parallax"
android:id="@+id/mealIV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_margin="10dp">
<LinearLayout
android:id="@+id/changemeal_LL"
android:layout_width="100dp"
android:layout_height="35dp"
android:background="@drawable/rounded_edge"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/change_meal"
android:textColor="@color/black_app_color"
android:textSize="@dimen/medium_text_size" />
</LinearLayout>
<LinearLayout
android:id="@+id/logLL"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginLeft="5dp"
android:background="@drawable/rounded_edge"
android:gravity="center">
<ImageView
android:layout_width="20dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:src="@mipmap/apple" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="@string/log_meal"
android:textColor="@color/black_app_color"
android:textSize="@dimen/medium_text_size" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/backLL"
android:layout_width="50dp"
android:layout_height="40dp"
android:gravity="center_vertical">
<ImageView
android:id="@+id/backIV"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginLeft="10dp"
android:src="@mipmap/back_img" />
</LinearLayout>
<ProgressBar
android:id="@+id/pb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
</LinearLayout>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="100dp"
android:visibility="gone"
app:layout_collapseMode="pin">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<include layout="@layout/meal_content_layout" />
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<View
android:layout_width="match_parent"
android:layout_height="10dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/tab_background">
<RadioGroup
android:id="@+id/activity_onsite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle">
<RadioButton
android:id="@+id/ingradient_radio"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:button="@null"
android:checked="true"
android:gravity="center"
android:padding="10dp"
android:text="@string/ingredients"
android:textColor="@color/black_app_color" />
<!--<view-->
<!--android:layout_width="1dp"-->
<!--android:layout_height="match_parent"-->
<!--android:layout_marginTop="5dp"-->
<!--android:layout_marginBottom="5dp"-->
<!--android:background="@color/tab_divider"/>-->
<RadioButton
android:id="@+id/preparation_radio"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:button="@null"
android:gravity="center"
android:padding="10dp"
android:text="@string/preparation"
android:textColor="@color/black_app_color" />
</RadioGroup>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1">
<View
android:id="@+id/ingradient_underline"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_weight="0.5"
android:background="@color/yellow" />
<View
android:id="@+id/preparation_underline"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_weight="0.5"
android:background="@color/yellow"
android:visibility="invisible" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/ingradientParentRV"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<TextView
android:id="@+id/preparationTV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/tab_line"
android:padding="10dp"
android:textSize="@dimen/medium_text_size"
android:visibility="gone" />
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</LinearLayout>
Это мой код активности:
public class MealPlanDetailActivity extends BaseActivity implements View.OnClickListener, AppBarLayout.OnOffsetChangedListener {
RadioButton inch_radio;
RadioButton cm_radio;
View inch_underline;
View cm_underline;
ImageView mealIV;
LinearLayout backLL;
LinearLayout logLL;
TextView mealNameTV;
TextView mealDetailTV;
TextView mealTimeTV;
TextView calTV;
TextView protTV;
TextView fatTV;
TextView cabTV;
TextView ingradientTV;
TextView preparationTV;
TextView preperationRecipeTVV;
TextView unsaturatedFatTV;
TextView saturatedFatTV;
TextView fiberTV;
RecyclerView ingradientRV;
RecyclerView ingradientParentRV;
Button selectMealBtn;
private LinearLayoutManager linearLayoutManager;
private LinearLayoutManager parentLinearLayoutManager;
ProgressBar pb;
Dialog dialog;
ImageView mealIVV;
ProgressBar pbb;
TextView recipeNameTV;
TextView timeTV;
LinearLayout changemeal_LL;
MealsDaysCommonStruct mealsDaysStruct;
PastryAndDrinkStruct pastryStruct;
FoodByDayDetailStruct struct;
MealsDaysCommonStruct recipeStruct;
TextView inGradientRecipeTV;
TextView preperationRecipeTV;
View inGradientRecipeV;
View preparatiomRecipeV;
ImageView selectedRecipeCloseIV;
int delayTime = 3000;
private float collapsedScale;
private float expandedScale;
Toolbar toolbar;
AppBarLayout mAppBarLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meal_explaination);
if (singleton.isUserAvailable()) {
mealsDaysStruct = (MealsDaysCommonStruct) getIntent().getSerializableExtra("SELECTED_MEAL");
pastryStruct = (PastryAndDrinkStruct) getIntent().getSerializableExtra("MEAL_CAKE_DRINK");
init();
setListener();
if (mealsDaysStruct != null)
makeGetMealDetailCall(true, mealsDaysStruct.getId());
else {
logLL.setVisibility(View.VISIBLE);
changemeal_LL.setVisibility(View.GONE);
makeGetMealDetailCall(true, pastryStruct.getId());
}
}
}
private void setData() {
if (singleton.isFav == 1) {
changemeal_LL.setVisibility(View.GONE);
}
mealNameTV.setText(struct.getName());
mealTimeTV.setText(struct.getMinutesForPreparation() + " min");
calTV.setText(struct.getCalories());
cabTV.setText(struct.getCarbs());
fatTV.setText(struct.getTotalFat());
protTV.setText(struct.getProteins());
unsaturatedFatTV.setText(struct.getUnsaturatedFats());
saturatedFatTV.setText(struct.getSaturatedFats());
fiberTV.setText(struct.getFiber());
singleton.loadImage(struct.getImageUrl(), mealIV, pb, false);
preparationTV.setText(Html.fromHtml(struct.getPreparation()));
ingradientParentRV.setAdapter(new IngradientAdapter(mAct, singleton.ingredientList));
}
private void init() {
struct = new FoodByDayDetailStruct();
inch_radio = findViewById(R.id.ingradient_radio);
cm_radio = findViewById(R.id.preparation_radio);
inch_underline = findViewById(R.id.ingradient_underline);
cm_underline = findViewById(R.id.preparation_underline);
calTV = findViewById(R.id.calTV);
protTV = findViewById(R.id.protTV);
fatTV = findViewById(R.id.fatTV);
cabTV = findViewById(R.id.cabTV);
backLL = findViewById(R.id.backLL);
preparationTV = findViewById(R.id.preparationTV);
pb = findViewById(R.id.pb);
mealNameTV = findViewById(R.id.mealNameTV);
mealDetailTV = findViewById(R.id.mealDetailTV);
mealTimeTV = findViewById(R.id.mealTimeTV);
mealIV = findViewById(R.id.mealIV);
logLL = findViewById(R.id.logLL);
unsaturatedFatTV = findViewById(R.id.unsaturatedFatTV);
saturatedFatTV = findViewById(R.id.saturatedFatTV);
fiberTV = findViewById(R.id.fiberTV);
changemeal_LL = findViewById(R.id.changemeal_LL);
ingradientParentRV = findViewById(R.id.ingradientParentRV);
parentLinearLayoutManager = new LinearLayoutManager(this);
ingradientParentRV.setLayoutManager(parentLinearLayoutManager);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mAppBarLayout = (AppBarLayout) findViewById(R.id.appbar);
mAppBarLayout.addOnOffsetChangedListener(this);
}
private void setListener() {
inch_radio.setOnClickListener(this);
cm_radio.setOnClickListener(this);
changemeal_LL.setOnClickListener(this);
logLL.setOnClickListener(this);
backLL.setOnClickListener(this);
mealIV.setOnClickListener(this);
}
public void setTabsPager(MealsDaysCommonStruct struct) {
this.mealsDaysStruct = struct;
makeGetMealDetailCall(false, mealsDaysStruct.getId());
}
@Override
public void onBackPressed() {
// singleton.commonStatus = singleton.Meal;
singleton.finishActivity();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ingradient_radio: {
inch_underline.setVisibility(View.VISIBLE);
cm_underline.setVisibility(View.INVISIBLE);
ingradientParentRV.setVisibility(View.VISIBLE);
preparationTV.setVisibility(View.GONE);
break;
}
case R.id.preparation_radio: {
preparationTV.setText(struct.getPreparation());
inch_underline.setVisibility(View.INVISIBLE);
cm_underline.setVisibility(View.VISIBLE);
ingradientParentRV.setVisibility(View.GONE);
preparationTV.setVisibility(View.VISIBLE);
break;
}
case R.id.backLL: {
// singleton.commonStatus = singleton.Meal;
onBackPressed();
break;
}
case R.id.changemeal_LL: {
if (singleton.loginStruct.getSubscriptionsList() != null && singleton.loginStruct.getSubscriptionsList().size() > 0) {
makeChangeMealCall();
} else {
// singleton.commonStatus = singleton.MEAL_DETAIL;
singleton.startActivity(SubscriptionsActivity.class, singleton.START_ACTIVITY);
}
break;
}
case R.id.logLL: {
makeLogMealCall();
break;
}
case R.id.inGradientRecipeTV: {
preperationRecipeTVV.setVisibility(View.GONE);
ingradientRV.setVisibility(View.VISIBLE);
inGradientRecipeV.setVisibility(View.VISIBLE);
preparatiomRecipeV.setVisibility(View.INVISIBLE);
break;
}
case R.id.preperationRecipeTV: {
preperationRecipeTVV.setVisibility(View.VISIBLE);
ingradientRV.setVisibility(View.GONE);
inGradientRecipeV.setVisibility(View.INVISIBLE);
preparatiomRecipeV.setVisibility(View.VISIBLE);
break;
}
case R.id.selectedRecipeCloseIV: {
dialog.dismiss();
break;
}
case R.id.selectMealBtn: {
// makeGetMealDetailCall(true,mealsDaysStruct.getId());
setData();
singleton.upDateMeal(struct);
singleton.isMealChange = true;
dialog.dismiss();
break;
}
case R.id.mealIV:{
Bundle bundle = new Bundle();
bundle.putString("ImageUrl" , struct.getImageUrl());
singleton.startActivityWithDataBundle(MealImageViewActivity.class , bundle , singleton.START_ACTIVITY);
break;
}
}
}
private void makeGetMealDetailCall(Boolean key, int mealId) {
singleton.showProgress(getString(R.string.please_wait));
Map<String, Object> params = new HashMap<>();
params.put("meal_id", mealId);
Call<Object> call = singleton.getApiInterface().postCall("Bearer " + singleton.TOKEN, "get-meal-detail", params);
OnServerResCallBack callBack = (status, message, responseStr) -> {
if (status == singleton.SUCCESS) {
JSONObject obj = singleton.parseSuccessPartOfJSON_OBJ(responseStr, "detail");
struct = gson.fromJson(obj.toString(), FoodByDayDetailStruct.class);
singleton.ingredientList = struct.getIngredients();
if (key == true) {
setData();
} else {
dialog();
setMealDetailDialog();
}
} else {
singleton.showCommonDialog(null, getString(R.string.error), message, getString(R.string.ok), false);
}
singleton.dismissProgress();
};
singleton.makePostCall(call, callBack);
}
private void makeLogMealCall() {
singleton.showProgress(getString(R.string.please_wait));
Map<String, Object> params = new HashMap<>();
params.put("meal_id", struct.getId());
params.put("meal_time_id", singleton.getMealTypeId(singleton, singleton.mealType));
if (singleton.isFav == 0) {
params.put("food_plan_id", singleton.loginStruct.getFoodStartedStruct().getFoodPlanId());
}
Call<Object> call = singleton.getApiInterface().postCall("Bearer " + singleton.TOKEN, "log-meal", params);
OnServerResCallBack callBack = (status, message, responseStr) -> {
if (status == singleton.SUCCESS) {
JSONObject obj = singleton.parseSuccessPartOfJSON_OBJ(responseStr, "award");
if (obj.has("message")) {
singleton.isLogMealAward = true;
} else {
OnDialogCallBack dialogCallBack = isOkClick -> singleton.finishActivity();
singleton.showDialog(dialogCallBack , getString(R.string.great) , getString(R.string.you_logged_your_meal) , "Ok" );
}
} else {
singleton.showCommonDialog(null, getString(R.string.error), message, getString(R.string.ok), false);
}
singleton.dismissProgress();
};
singleton.makePostCall(call, callBack);
}
public void showDialogChangeMealSelection(FoodByDayDetailStruct detailStruct) {
struct = detailStruct;
makeGetMealDetailCall(false, struct.getId());
}
public void dialog() {
dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.dialog_change_meal_selection);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
initDialog();
setListenerDialod();
dialog.show();
}
private void setListenerDialod() {
inGradientRecipeTV.setOnClickListener(this);
preperationRecipeTV.setOnClickListener(this);
selectedRecipeCloseIV.setOnClickListener(this);
selectMealBtn.setOnClickListener(this);
}
private void initDialog() {
mealIVV = dialog.findViewById(R.id.mealIVV);
pbb = dialog.findViewById(R.id.pbb);
recipeNameTV = dialog.findViewById(R.id.recipeNameTV);
timeTV = dialog.findViewById(R.id.timeTV);
preperationRecipeTV = dialog.findViewById(R.id.preperationRecipeTV);
inGradientRecipeV = dialog.findViewById(R.id.inGradientRecipeV);
preparatiomRecipeV = dialog.findViewById(R.id.preparatiomRecipeV);
inGradientRecipeTV = dialog.findViewById(R.id.inGradientRecipeTV);
selectedRecipeCloseIV = dialog.findViewById(R.id.selectedRecipeCloseIV);
preperationRecipeTVV = dialog.findViewById(R.id.preperationRecipeTVV);
ingradientRV = dialog.findViewById(R.id.ingradientRV);
selectMealBtn = dialog.findViewById(R.id.selectMealBtn);
}
private void makeChangeMealCall() {
singleton.showProgress(getString(R.string.please_wait));
Map<String, Object> params = new HashMap<>();
params.put("food_plan_id", singleton.loginStruct.getFoodStartedStruct().getFoodPlanId());
params.put("meal_time_id", singleton.getMealTypeId(singleton, singleton.mealType));
Call<Object> call = singleton.getApiInterface().postCall("Bearer " + singleton.TOKEN, "get-meals-for-change", params);
OnServerResCallBack callBack = (status, message, responseStr) -> {
if (status == singleton.SUCCESS) {
JSONArray jsonArray = singleton.parseSuccessPartOfJSON(responseStr, "meals");
List<FoodByDayDetailStruct> list = gson.fromJson(jsonArray.toString(), new TypeToken<ArrayList<FoodByDayDetailStruct>>() {
}.getType());
Collections.shuffle(list);
singleton.showDialogChangeMeal(mAct, struct.getId(), list);
} else {
singleton.showCommonDialog(null, getString(R.string.error), message, getString(R.string.ok), false);
}
singleton.dismissProgress();
};
singleton.makePostCall(call, callBack);
}
private void setMealDetailDialog() {
linearLayoutManager = new LinearLayoutManager(this);
ingradientRV.setLayoutManager(linearLayoutManager);
recipeNameTV.setText(struct.getName());
timeTV.setText(struct.getMinutesForPreparation().toString() + " min");
preperationRecipeTVV.setText(Html.fromHtml(struct.getPreparation()));
singleton.loadImage(struct.getImageUrl(), mealIVV, pbb, false);
ingradientRV.setAdapter(new IngradientAdapter(mAct, singleton.ingredientList));
}
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
int maxScroll = appBarLayout.getTotalScrollRange();
float scrollPercent = (float) Math.abs(i) / (float) maxScroll;
if (collapsedScale == 0) {
Drawable photo = mealIV.getDrawable();
int bitmapWidth = photo.getIntrinsicWidth();
int bitmapHeight = photo.getIntrinsicHeight();
collapsedScale = (float)mealIV.getWidth()/(float)bitmapWidth;
expandedScale = (float)mealIV.getHeight()/(float)bitmapHeight;
scalePhotoImage(mealIV, expandedScale);
} else {
scalePhotoImage(mealIV, collapsedScale + (expandedScale - collapsedScale) * (1f - scrollPercent));
}
}
private static void scalePhotoImage(ImageView photoView, float scale) {
Drawable photo = photoView.getDrawable();
int bitmapWidth = photo.getIntrinsicWidth();
int bitmapHeight = photo.getIntrinsicHeight();
float offsetX = (photoView.getWidth() - bitmapWidth) / 2F;
float offsetY = (photoView.getHeight() - bitmapHeight) / 2F;
float centerX = photoView.getWidth() / 2F;
float centerY = photoView.getHeight() / 2F;
Matrix imageMatrix = new Matrix();
imageMatrix.setScale(scale, scale, centerX, centerY);
imageMatrix.preTranslate(offsetX, offsetY);
photoView.setImageMatrix(imageMatrix);
}
}