gpt4 book ai didi

带有基于自定义操作提供程序的垂直(旋转)文本项的 Android ActionBar 菜单

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:03:14 28 4
gpt4 key购买 nike

我正在向操作栏项目添加菜单。菜单将包含每个项目的垂直文本。菜单包含什么并不重要。我基本上只想创建自己的 View ,当我按下操作栏项目时会弹出该 View 。所以为了这个问题的目的,你可以把我的观点想象成一个大黑盒子。

enter image description here

右边的图像是用 Gimp 制作的。这是我正在尝试做的,而不是我已经完成的。

我尝试过的

为了使用 Material Design 主题更新旧应用,我一直在浏览所有 lessons in the Android documentation for adding the app bar .由于我的垂直文本菜单不适合常见情况,因此我必须制作一个自定义 Action Provider。 documentation但是,没有提供自定义操作提供程序的完整示例。我能找到的最好的是 this Stack Overflow answer .

下图显示了我能做的最好的(黑色 View 代表我 future 的菜单):

enter image description here

上图中的星星目前有 Action 提供者。但是,自定义 View 在操作栏中被剪掉了。我如何让它漂浮在一切之上?另外,在单击操作栏项目之前,我不希望它出现。不过目前,它只是立即显示。

代码

主 Activity .java

public class MainActivity extends AppCompatActivity  {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// setup toolbar
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);

...
}

public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
// User chose the "Settings" item, show the app settings UI...
return true;

case R.id.action_favorite:
// User chose the "Favorite" action, mark the current item
// as a favorite...
return true;

default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);

}
}

...
}

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:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">

<android.support.v7.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

...

菜单.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item
android:id="@+id/action_favorite"
android:icon="@drawable/ic_star_black_24dp"
android:title="@string/menu_favorites"
app:actionProviderClass="com.example.chimee.MyActionProvider"
app:showAsAction="ifRoom"/>

<item android:id="@+id/action_settings"
android:title="@string/menu_item_settings"
app:showAsAction="never"/>

</menu>

MyActionProvider.java

import android.content.Context;
import android.support.v4.view.ActionProvider;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;

public class MyActionProvider extends ActionProvider {

private Context mContext;

public MyActionProvider(Context context) {
super(context);

mContext = context;
}

// for versions older than api 16
@Override
public View onCreateActionView() {
// Inflate the action provider to be shown on the action bar.
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View providerView =
layoutInflater.inflate(R.layout.my_action_provider, null);
View myView =
(View) providerView.findViewById(R.id.blackView);
myView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("myTag", "black view was clicked");
}
});
return providerView;
}

@Override
public View onCreateActionView(MenuItem forItem) {
// TODO: don't just repeat all this code here from above.
// Inflate the action provider to be shown on the action bar.
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View providerView =
layoutInflater.inflate(R.layout.my_action_provider, null);
View myView =
(View) providerView.findViewById(R.id.blackView);
myView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("myTag", "black view was clicked");
}
});
return providerView;
}
}

my_action_provider.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?attr/actionButtonStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="?attr/actionBarItemBackground"
android:focusable="true" >

<View
android:id="@+id/blackView"
android:layout_width="200dp"
android:layout_height="150dp"
android:background="#000000" />

</LinearLayout>

我很高兴看到任何功能齐全的自定义操作提供程序在操作栏框架之外显示 View 的示例。

最佳答案

如果您没有找到基于自定义操作提供程序的解决方案,可能是您想要使用自定义 Toolbar & PopupWindow -based 解决方法,这意味着:

1) 使用 ImageButton 作为菜单按钮创建自定义 Toolbar 并用它替换 ActionBar(如 that 中的 Machado 帖子) );

2) 创建 PopupWindow 并为带有垂直文本的菜单项自定义布局;

3) 将 onClickListener 添加到 p.1 中的 ImageButton,它显示 p.2 中的 PopupWindow

自定义工具栏(action_bar.xml)的布局可能是这样的:

<?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="?attr/actionBarSize"
android:layout_gravity="fill_horizontal"
android:orientation="vertical">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="@color/colorPrimary"
android:elevation="4dp"
android:layout_height="?attr/actionBarSize">
</android.support.v7.widget.Toolbar>
</RelativeLayout>

使用它的 MainActivity 布局(activity_main.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/activity_main"
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:padding="0dp"
tools:context="<your_package_name>.MainActivity">

<include
android:id="@+id/tool_bar"
layout="@layout/action_bar"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:layout_marginStart="31dp"
android:layout_below="@+id/tool_bar"
android:layout_alignParentStart="true"
android:layout_marginTop="31dp"/>

</RelativeLayout>

ImageButton 作为“主弹出菜单”按钮在 main_menu.xml 文件中以这种方式描述(更多内容在 this ASH 的帖子中):

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_button"
android:icon="@drawable/ic_more_vert"
android:title=""
app:showAsAction="always"
app:actionViewClass="android.widget.ImageButton"/>
</menu>

对于菜单项的垂直文本您可以使用,例如,自定义View,如来自thisVerticalLabelViewkostmo :

public class VerticalLabelView extends View {
private TextPaint mTextPaint;
private String mText;
private int mAscent;
private Rect text_bounds = new Rect();

final static int DEFAULT_TEXT_SIZE = 15;

public VerticalLabelView(Context context) {
super(context);
initLabelView();
}

public VerticalLabelView(Context context, AttributeSet attrs) {
super(context, attrs);
initLabelView();

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VerticalLabelView);

CharSequence s = a.getString(R.styleable.VerticalLabelView_text);
if (s != null) setText(s.toString());

setTextColor(a.getColor(R.styleable.VerticalLabelView_textColor, 0xFF000000));

int textSize = a.getDimensionPixelOffset(R.styleable.VerticalLabelView_textSize, 0);
if (textSize > 0) setTextSize(textSize);

a.recycle();
}

private final void initLabelView() {
mTextPaint = new TextPaint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(DEFAULT_TEXT_SIZE);
mTextPaint.setColor(0xFF000000);
mTextPaint.setTextAlign(Align.CENTER);
setPadding(3, 3, 3, 3);
}

public void setText(String text) {
mText = text;
requestLayout();
invalidate();
}

public void setTextSize(int size) {
mTextPaint.setTextSize(size);
requestLayout();
invalidate();
}

public void setTextColor(int color) {
mTextPaint.setColor(color);
invalidate();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

mTextPaint.getTextBounds(mText, 0, mText.length(), text_bounds);
setMeasuredDimension(
measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}

private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);

if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = text_bounds.height() + getPaddingLeft() + getPaddingRight();

if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}

private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);

mAscent = (int) mTextPaint.ascent();
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = text_bounds.width() + getPaddingTop() + getPaddingBottom();

if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

float text_horizontally_centered_origin_x = getPaddingLeft() + text_bounds.width()/2f;
float text_horizontally_centered_origin_y = getPaddingTop() - mAscent;

canvas.translate(text_horizontally_centered_origin_y, text_horizontally_centered_origin_x);
canvas.rotate(-90);
canvas.drawText(mText, 0, 0, mTextPaint);
}
}

(注意:您可能需要自定义 VerticalLabelView 的填充:在线result = text_bounds.height() + getPaddingLeft() + getPaddingRight() + 16;添加“+16”以获得更好的填充)

attrs.xml 用于 VerticalLabelView 类:

<resources>
<declare-styleable name="VerticalLabelView">
<attr name="text" format="string" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>

PopupWindow 的布局 (menu_layout.xml) 在这种情况下可能是这样的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/menu_root"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/activity_horizontal_margin">

<<your_package_name>.VerticalLabelView
android:id="@+id/menu_item1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 1"/>

<<your_package_name>.VerticalLabelView
android:id="@+id/menu_item2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 2"/>

<<your_package_name>.VerticalLabelView
android:id="@+id/menu_item3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 3"/>

<<your_package_name>.VerticalLabelView
android:id="@+id/menu_item4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 4"/>

</LinearLayout>

MainActivity 类可以是这样的:

public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();

private Toolbar mToolbar;
private int mToolbarTitleColor;
private ImageButton mMainMenuButton;
private int mActionBarSize;
private PopupWindow mPopupMenu;
private int mTextSize = 48;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
mActionBarSize = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}

mToolbarTitleColor = Color.WHITE;
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setTitleTextColor(mToolbarTitleColor);

setSupportActionBar(mToolbar);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);

Drawable menuIcon = ContextCompat.getDrawable(this, R.drawable.ic_more_vert);
menuIcon.setColorFilter(mToolbarTitleColor, PorterDuff.Mode.SRC_ATOP);

getMenuInflater().inflate(R.menu.main_menu, menu);
mMainMenuButton = (ImageButton) menu.findItem(R.id.menu_button).getActionView();
mMainMenuButton.setBackground(null);
mMainMenuButton.setImageDrawable(menuIcon);
mMainMenuButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPopupMenu != null && mPopupMenu.isShowing()) {
mPopupMenu.dismiss();
}
mPopupMenu = createPopupMenu();
mPopupMenu.showAtLocation(v, Gravity.TOP | Gravity.RIGHT, 0, mActionBarSize);
}
});
return true;
}

public PopupWindow createPopupMenu() {
final PopupWindow popupWindow = new PopupWindow(this);
LayoutInflater inflater = getLayoutInflater();

View popupView = inflater.inflate(R.layout.menu_layout, null);

VerticalLabelView menuItem1 = (VerticalLabelView)popupView.findViewById(R.id.menu_item1);
menuItem1.setOnClickListener(mOnMenuItemClickListener);
menuItem1.setText("Vertical menu item 1");
menuItem1.setTextColor(Color.WHITE);
menuItem1.setTextSize(mTextSize);

VerticalLabelView menuItem2 = (VerticalLabelView)popupView.findViewById(R.id.menu_item2);
menuItem2.setOnClickListener(mOnMenuItemClickListener);
menuItem2.setText("Vertical menu item 2");
menuItem2.setTextColor(Color.WHITE);
menuItem2.setTextSize(mTextSize);

VerticalLabelView menuItem3 = (VerticalLabelView)popupView.findViewById(R.id.menu_item3);
menuItem3.setOnClickListener(mOnMenuItemClickListener);
menuItem3.setText("Vertical menu item 3");
menuItem3.setTextColor(Color.WHITE);
menuItem3.setTextSize(mTextSize);

VerticalLabelView menuItem4 = (VerticalLabelView)popupView.findViewById(R.id.menu_item4);
menuItem4.setOnClickListener(mOnMenuItemClickListener);
menuItem4.setText("Vertical menu item 4");
menuItem4.setTextColor(Color.WHITE);
menuItem4.setTextSize(mTextSize);

popupWindow.setFocusable(true);
popupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setContentView(popupView);

return popupWindow;
}

private View.OnClickListener mOnMenuItemClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.menu_item1: {
Log.d(TAG, "menu_item1");
}
break;
case R.id.menu_item2: {
Log.d(TAG, "menu_item2");
}
break;
case R.id.menu_item3: {
Log.d(TAG, "menu_item3");
}
case R.id.menu_item4: {
Log.d(TAG, "menu_item4");
}
break;
default: {
}
}
if (mPopupMenu != null && mPopupMenu.isShowing()) {
mPopupMenu.dismiss();
}
}
};
}

最终,作为结果,您应该收到类似的东西:

Vertical menu items screenshot

附言当然,对于 createPopupMenu(),您需要更优雅的解决方案。

关于带有基于自定义操作提供程序的垂直(旋转)文本项的 Android ActionBar 菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39304883/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com