【发布时间】:2017-05-04 14:08:25
【问题描述】:
【问题讨论】:
-
我认为小吃店不可能。你为什么不创建一个自定义小部件。
-
也许你可以尝试反射......但这不是一个容易的恕我直言
-
你已经完成了一些代码,请分享。
标签: android android-snackbar snackbar
【问题讨论】:
标签: android android-snackbar snackbar
【讨论】:
setAction()。没有像 addAction() 这样你不能添加 2 个动作。
感谢 Shailesh,我必须修改代码才能使其适合我。
my_snackbar.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:id="@+id/my_snackbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dark_grey"
android:padding="15dp">
<TextView
android:id="@+id/message_text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".6"
android:gravity="center_vertical"
android:text="Two button snackbar"
android:textColor="@color/white"/>
<TextView
android:id="@+id/first_text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".2"
android:gravity="center"
android:text="ONE"
android:textColor="#FFDEAD"/>
<TextView
android:id="@+id/second_text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".2"
android:gravity="center"
android:text="TWO"
android:textColor="#FFDEAD"/>
</LinearLayout>
在您的活动中,只要您想显示小吃栏,就调用此方法:
private void showTwoButtonSnackbar() {
// Create the Snackbar
LinearLayout.LayoutParams objLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
snackbar = Snackbar.make(this.findViewById(android.R.id.content), message, Snackbar.LENGTH_INDEFINITE);
// Get the Snackbar layout view
Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView();
// Set snackbar layout params
int navbarHeight = getNavBarHeight(this);
FrameLayout.LayoutParams parentParams = (FrameLayout.LayoutParams) layout.getLayoutParams();
parentParams.setMargins(0, 0, 0, 0 - navbarHeight + 50);
layout.setLayoutParams(parentParams);
layout.setPadding(0, 0, 0, 0);
layout.setLayoutParams(parentParams);
// Inflate our custom view
View snackView = getLayoutInflater().inflate(R.layout.my_snackbar, null);
// Configure our custom view
TextView messageTextView = (TextView) snackView.findViewById(R.id.message_text_view);
messageTextView.setText(message);
TextView textViewOne = (TextView) snackView.findViewById(R.id.first_text_view);
textViewOne.setText("ALLOW");
textViewOne.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Allow", "showTwoButtonSnackbar() : allow clicked");
snackbar.dismiss();
}
});
TextView textViewTwo = (TextView) snackView.findViewById(R.id.second_text_view);
textViewTwo.setText("DENY");
textViewTwo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Deny", "showTwoButtonSnackbar() : deny clicked");
snackbar.dismiss();
}
});
// Add our custom view to the Snackbar's layout
layout.addView(snackView, objLayoutParams);
// Show the Snackbar
snackbar.show();
}
获取导航栏高度:
public static int getNavBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
【讨论】:
作为@Elias N 的答案,每个Snackbar 可能包含一个动作。如果您想在Snackbar 中设置更多操作,那么您需要创建自己的布局。请试试这个,希望对你有帮助。
创建一个xml文件my_snackbar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#000000">
<TextView
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight=".7"
android:gravity="center_vertical"
android:text="Please select any one"
android:textColor="@color/white"/>
<TextView
android:id="@+id/txtOne"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight=".1"
android:gravity="center"
android:text="ONE"
android:textColor="@color/red"/>
<TextView
android:id="@+id/txtTwo"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight=".1"
android:gravity="center"
android:text="TWO"
android:textColor="@color/red"/>
</LinearLayout>
现在在您的活动文件中执行以下代码。
public void myCustomSnackbar()
{
// Create the Snackbar
LinearLayout.LayoutParams objLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
Snackbar snackbar = Snackbar.make(llShow, "", Snackbar.LENGTH_LONG);
// Get the Snackbar's layout view
Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView();
layout.setPadding(0,0,0,0);
// Hide the text
TextView textView = (TextView) layout.findViewById(android.support.design.R.id.snackbar_text);
textView.setVisibility(View.INVISIBLE);
LayoutInflater mInflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
// Inflate our custom view
View snackView = getLayoutInflater().inflate(R.layout.my_snackbar, null);
// Configure the view
TextView textViewOne = (TextView) snackView.findViewById(R.id.txtOne);
textViewOne.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("One", "First one is clicked");
}
});
TextView textViewTwo = (TextView) snackView.findViewById(R.id.txtTwo);
textViewTwo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("Two", "Second one is clicked");
}
});
// Add the view to the Snackbar's layout
layout.addView(snackView, objLayoutParams);
// Show the Snackbar
snackbar.show();
}
更多详情请阅读this documentation和here。
【讨论】:
setView() 方法。
您可以使用BottomSheetDialog 并将其伪装成SnackBar。唯一的区别是它将通过向下滑动而不是向右滑动来解除它,并且它可以一直呆在那里直到用户解除它,而 SnackBar 最终消失。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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/fragment_history_menu_bottom"
style="@style/Widget.Design.BottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:background="@color/cardview_dark_background"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/appCompatTextView"
android:layout_width="wrap_content"
android:layout_height="19dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_weight="0.6"
android:text="Load More ?"
android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"
android:textColor="@color/cardview_light_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/fragment_history_bottom_sheet_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|end"
android:layout_weight="0.4"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<android.support.v7.widget.AppCompatButton
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Yes" />
<android.support.v7.widget.AppCompatButton
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No"
android:textColor="@color/cardview_light_background" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
并按照以下方式使用它(Kotlin)
val dialog = BottomSheetDialog(this)
dialog.setContentView(this.layoutInflater.inflate(R.layout.bottom_sheet_load_prompt,null))
dialog.show()
结果将类似于 SnackBar
【讨论】:
这是一个带有 Kotlin 的 proper solution,我在处理 Fulguris 时首次部署它。
使用 Kotlin 扩展,我们将 Snackbar 类扩展如下:
/**
* Adds an extra action button to this snackbar.
* [aLayoutId] must be a layout with a Button as root element.
* [aLabel] defines new button label string.
* [aListener] handles our new button click event.
*/
fun Snackbar.addAction(@LayoutRes aLayoutId: Int, @StringRes aLabel: Int, aListener: View.OnClickListener?) : Snackbar {
addAction(aLayoutId,context.getString(aLabel),aListener)
return this;
}
/**
* Adds an extra action button to this snackbar.
* [aLayoutId] must be a layout with a Button as root element.
* [aLabel] defines new button label string.
* [aListener] handles our new button click event.
*/
fun Snackbar.addAction(@LayoutRes aLayoutId: Int, aLabel: String, aListener: View.OnClickListener?) : Snackbar {
// Add our button
val button = LayoutInflater.from(view.context).inflate(aLayoutId, null) as Button
// Using our special knowledge of the snackbar action button id we can hook our extra button next to it
view.findViewById<Button>(R.id.snackbar_action).let {
// Copy layout
button.layoutParams = it.layoutParams
// Copy colors
(button as? Button)?.setTextColor(it.textColors)
(it.parent as? ViewGroup)?.addView(button)
}
button.text = aLabel
/** Ideally we should use [Snackbar.dispatchDismiss] instead of [Snackbar.dismiss] though that should do for now */
//extraView.setOnClickListener {this.dispatchDismiss(BaseCallback.DISMISS_EVENT_ACTION); aListener?.onClick(it)}
button.setOnClickListener {this.dismiss(); aListener?.onClick(it)}
return this;
}
然后我们需要定义我们的按钮资源:
<?xml version="1.0" encoding="utf-8"?>
<!--
Used to create and extra button in our snackbar popup messages.
Though most properties including layout params and colors are overridden at runtime.
They are just copied from the standard snackbar action button to make sure they both lookalike.
-->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/snackbar_extra_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginStart="0dp"
android:layout_gravity="center_vertical|right|end"
android:paddingTop="14dp"
android:paddingBottom="14dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textColor="?attr/colorAccent"
style="?attr/borderlessButtonStyle"/>
这是你如何使用它:
Snackbar.make(aView, aMessage, aDuration).setAction(R.string.button_one) {
// Do your thing after regular button press
}.addAction(R.layout.snackbar_extra_button, R.string.button_two){
//Do your thing after extra button push
}.show()
【讨论】:
您可以尝试另一种 hacky 解决方法(在我的情况下有效)。
final Snackbar snackbar = Snackbar.make(view, "UNDO MARKED AS READ", Snackbar.LENGTH_LONG);
snackbar.setAction("DISMISS", new View.OnClickListener() {
@Override
public void onClick(View v) {
if (snackbar != null)
snackbar.dismiss();
}
});
View snackbarView = snackbar.getView();
int snackbarTextId = android.support.design.R.id.snackbar_text;
TextView textView = (TextView) snackbarView.findViewById(snackbarTextId);
textView.setTextColor(Color.WHITE);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (snackbar != null)
snackbar.dismiss();
// undo mark as unread code
}
});
snackbar.show();
【讨论】:
遵循 Shaileshs 解决方案:
小吃店类
public class SnackbarOfflineErrorNotification {
/**
* A view from the content layout.
*/
@NonNull
private final View view;
@NonNull
private Context context;
/**
* The snack bar being shown.
*/
@Nullable
private Snackbar snackbar = null;
/**
* Construct a new instance of the notification.
*
* @param view A view from the content layout, used to seek an appropriate anchor for the
* Snackbar.
*/
public SnackbarOfflineErrorNotification(@NonNull final View view, @NonNull Context context) {
this.view = view;
this.context = context;
}
public void showOfflineError (){
if (snackbar == null){
//create snackbar
snackbar = Snackbar.make(this.view, R.string.offline_text, LENGTH_INDEFINITE);
// Create the Snackbar
LinearLayout.LayoutParams objLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// Get the Snackbar's layout view
Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView();
layout.setPadding(0,0,0,0);
// Hide the text
TextView textView = (TextView) layout.findViewById(android.support.design.R.id.snackbar_text);
textView.setVisibility(View.INVISIBLE);
// Inflate our custom view
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View snackView = inflater.inflate(R.layout.snackbar_offline, null);
// Configure the view
Button btnOne = (Button) snackView.findViewById(R.id.btnOne);
btnOne.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// action 1
}
});
Button btnTwo = (Button) snackView.findViewById(R.id.btnTwo);
btnTwo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// action 2
}
});
// Add the view to the Snackbar's layout
layout.addView(snackView, objLayoutParams);
// Show the Snackbar
snackbar.show();
}
}
/**
* Hides the currently displayed error.
*/
public void hideError() {
if (snackbar != null) {
snackbar.dismiss();
snackbar = null;
}
}
}
小吃吧 xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#000000">
<TextView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_weight=".7"
android:gravity="center_vertical"
android:text="offline"
android:textColor="@color/white"
android:paddingLeft="16dp"/>
<Button
android:id="@+id/btnOne"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_weight=".1"
android:gravity="center"
android:text="one" />
<Button
android:id="@+id/btnTwo"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_weight=".1"
android:gravity="center"
android:text="two"/>
</LinearLayout>
目标活动
constructor(){
snackbarOfflineErrorNotification = new SnackbarOfflineErrorNotification(findViewById(R.id.coordinator_layout), getApplicationContext());
}
public void hideSnackbar(){
snackbarOfflineErrorNotification.hideError();
}
public showSnackbar(){
snackbarOfflineErrorNotification.showOfflineError();
}
【讨论】:
您可以将“解雇”用作其他操作
Snackbar snackbar = Snackbar.make(requireView(), "Marked as read", BaseTransientBottomBar.LENGTH_SHORT);
snackbar.setAction("undo", view -> {
//undo action
});
snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
//dismiss action
}
});
snackbar.show();
【讨论】: