我有一个自定义 View ,用于在 Canvas 上绘制不同尺寸和图像。这很棒。所以每次我画东西时,我都会将这些信息添加到 actionList 中。
当用户退出应用程序时,我将此 actionList 作为字符串保存到 sharedPreference。当用户重新打开应用程序时,我正在获取此数据并使用 Gson 将其转换回 List previous_drawn_paths 并以此更新 actionList。
当我执行此操作时出现段错误,但存在数据和内存引用。我也附上了代码和墓碑 logcat。
绘图 View .java
public class DrawingView extends View {
public enum Type {
PATH,
TEXT,
STAMP;
}
/**
* Different type of draw
*/
public enum Mode {
DRAW,
ERASER,
TEXT,
STAMP;
}
/**
* Different Modes for Drawing
*/
public enum Drawer {
PEN,
LINE,
ELLIPSE;
}
/**
* Different Modes of Stamps
*/
public enum Stamper {
STAR,
THUMB;
}
private Context context = null;
private Canvas canvas = null;
private Bitmap bitmap = null;
private int width;
private int height;
private int historyPointer = 0;
private List<DrawingAction> previous_action_list = new ArrayList<>();
private String TAG = this.getClass().getCanonicalName();
public List<DrawingAction> getPrevious_action_list() {
return previous_action_list;
}
public void setPrevious_action_list(List<DrawingAction> previous_action_list) {
this.previous_action_list = previous_action_list;
updateHistoryPath();
}
/**
* Collection of different types of actions
*/
private List<DrawingAction> actionLists = new ArrayList<>();
public List<DrawingAction> getActionLists() {
return actionLists;
}
/**
* Flags for maintaining the states
*/
private boolean enabled = false;
private boolean isDown = false;
private Mode mode = Mode.DRAW;
private Drawer drawer = Drawer.PEN;
private Stamper stamper = Stamper.STAR;
private float startX = 0F;
private float startY = 0F;
private Paint drawPaint;
private Paint erasePaint;
private Paint textPaint;
private Bitmap starPaint;
private Bitmap thumbPaint;
public DrawingView(Context context) {
super(context);
this.setup(context);
}
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setup(context);
}
public DrawingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.setup(context);
}
private void setup(Context context) {
this.context = context;
createDrawPaint();
createErasePaint();
createTextPaint();
createStamperPaint(context);
}
private void createDrawPaint() {
this.drawPaint = new Paint();
this.drawPaint.setAntiAlias(true);
this.drawPaint.setStyle(Paint.Style.STROKE);
this.drawPaint.setStrokeWidth(10F);
this.drawPaint.setStrokeCap(Paint.Cap.BUTT);
this.drawPaint.setStrokeJoin(Paint.Join.MITER);
this.drawPaint.setColor(Color.RED);
this.drawPaint.setAlpha(255);
}
private void createErasePaint() {
this.erasePaint = new Paint();
this.erasePaint.setColor(Color.WHITE);
this.erasePaint.setAlpha(255);
this.erasePaint.setAntiAlias(true);
this.erasePaint.setDither(true);
this.erasePaint.setStyle(Paint.Style.STROKE);
this.erasePaint.setStrokeJoin(Paint.Join.ROUND);
this.erasePaint.setStrokeCap(Paint.Cap.ROUND);
this.erasePaint.setStrokeWidth(10F);
}
private void createTextPaint() {
this.textPaint = new Paint();
this.textPaint.setAntiAlias(true);
this.textPaint.setStyle(Paint.Style.STROKE);
this.textPaint.setStrokeCap(Paint.Cap.BUTT);
this.textPaint.setStrokeJoin(Paint.Join.MITER);
this.textPaint.setTypeface(Typeface.DEFAULT);
this.textPaint.setTextSize(56F);
this.textPaint.setTextAlign(Paint.Align.RIGHT);
this.drawPaint.setColor(Color.RED);
this.textPaint.setStrokeWidth(0F);
}
private void createStamperPaint(Context context) {
this.starPaint = BitmapFactory.decodeResource(context.getResources(), R.mipmap.stamp_star);
this.thumbPaint = BitmapFactory.decodeResource(context.getResources(), R.mipmap.stamp_thumb);
}
private DrawingAction getCurrentAction() {
return this.actionLists.get(this.historyPointer-1);
}
private void drawText(DrawingAction action, Canvas canvas) {
String text = action.getText();
if((text == null) || (text.length() <= 0)) {
return;
}
float textX = action.getPositionX();
float textY = action.getPositionY();
Paint paintMeasureText = new Paint();
float textLength = paintMeasureText.measureText(text);
float lengthOfChar = textLength / (float) text.length();
float restWidth = this.canvas.getWidth() - textX; // text-align : right
int numChars = (lengthOfChar <= 0) ? 1 : (int) Math.floor((double) (restWidth / lengthOfChar)); // The number of characters at 1 line
int modNumChars = (numChars < 1) ? 1 : numChars;
float y = textY;
for (int i = 0, len = text.length(); i < len; i += modNumChars) {
String substring = "";
if ((i + modNumChars) < len) {
substring = text.substring(i, (i + modNumChars));
} else {
substring = text.substring(i, len);
}
//TODO: Adjust according to the font size
y += 56F;
canvas.drawText(substring, textX, y, this.textPaint);
}
}
private void updateHistory(DrawingAction action) {
if (this.historyPointer == this.actionLists.size()) {
this.actionLists.add(action);
Log.d(TAG,"history pointer update"+this.historyPointer);
this.historyPointer++;
} else {
// Removing the unused actions in history
this.actionLists.set(this.historyPointer, action);
this.historyPointer++;
for (int i = this.historyPointer, size = this.actionLists.size(); i < size; i++) {
this.actionLists.remove(this.historyPointer);
}
}
}
private void updateHistoryPath()
{
for(int index=0 ; index<previous_action_list.size(); index++)
{
Log.d(TAG,"adding canvas index from previous list"+index);
if (previous_action_list.get(index).getType()!=null)
{
updateHistory(new DrawingAction(previous_action_list.get(index).getType(),previous_action_list.get(index).getPath(),previous_action_list.get(index).getPaint()));
}
}
}
public boolean undo() {
if (this.historyPointer > 1) {
this.historyPointer--;
this.invalidate();
return true;
} else {
return false;
}
}
public boolean redo() {
if (this.historyPointer < this.actionLists.size()) {
this.historyPointer++;
this.invalidate();
return true;
} else {
return false;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.TRANSPARENT);
if (this.bitmap != null) {
canvas.drawBitmap(this.bitmap, 0F, 0F, new Paint());
}
// this.historyPointer
for (int i = 0; i < this.historyPointer; i++) {
DrawingAction action = this.actionLists.get(i);
Type type = action.getType();
if(type == Type.PATH) {
canvas.drawPath(action.getPath(), action.getPaint());
Log.d("lingaraj","on draw history index"+i);
}
else if(type == Type.TEXT) {
this.drawText(action, canvas);
}
else if(type == Type.STAMP) {
Stamper stamper = action.getStamper();
if(stamper == Stamper.STAR) {
canvas.drawBitmap(this.starPaint, action.getPositionX(), action.getPositionY(), new Paint());
}
else if(stamper == Stamper.THUMB) {
canvas.drawBitmap(this.thumbPaint, action.getPositionX(), action.getPositionY(), new Paint());
}
}
}
this.canvas = canvas;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
public void setCustomWidth(int width) {
this.width = width;
}
public int getCustomWidth() {
return this.width;
}
public void setCustomHeight(int height) {
this.height = height;
}
public int getCustomHeight() {
return this.height;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean getEnabled() {
return this.enabled;
}
public void setMode(Mode mode) {
this.mode = mode;
}
public Mode getMode() {
return this.mode;
}
public void setDrawer(Drawer drawer) {
this.drawer = drawer;
this.mode = Mode.DRAW;
}
public void setStamper(Stamper stamper) {
this.stamper = stamper;
this.mode = Mode.STAMP;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
invalidate();
}
}
DrawingAction.java:
public class DrawingAction {
private DrawingView.Type type;
private Path path;
private Paint paint;
private String text;
private DrawingView.Stamper stamper;
private float positionX;
private float positionY;
public DrawingAction(DrawingView.Type type, Path path, Paint paint) {
this.type = type;
this.path = path;
this.paint = paint;
}
public DrawingAction(DrawingView.Type type, Path path, Paint paint, float positionX, float positionY) {
this.type = type;
this.path = path;
this.paint = paint;
this.positionX = positionX;
this.positionY = positionY;
}
public DrawingAction(DrawingView.Type type, String text, float positionX, float positionY) {
this.type = type;
this.text = text;
this.positionX = positionX;
this.positionY = positionY;
}
public DrawingAction(DrawingView.Type type, DrawingView.Stamper stamper, float positionX, float positionY) {
this.type = type;
this.stamper = stamper;
this.positionX = positionX;
this.positionY = positionY;
}
public DrawingView.Type getType() {
return type;
}
public Path getPath() {
return path;
}
public void setPath(Path path) {
this.path = path;
}
public Paint getPaint() {
return paint;
}
public void setPaint(Paint paint) {
this.paint = paint;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public DrawingView.Stamper getStamper() {
return stamper;
}
public void setStamper(DrawingView.Stamper stamper) {
this.stamper = stamper;
}
public float getPositionX() {
return positionX;
}
public void setPositionX(float positionX) {
this.positionX = positionX;
}
public float getPositionY() {
return positionY;
}
public void setPositionY(float positionY) {
this.positionY = positionY;
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
public static final String TAG = "Draw";
private DrawingView drawing;
private CanvasScroll scroll;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_correct);
drawing = (DrawingView) findViewById(R.id.canvasDrawing);
List<DrawingAction> drawing_action_list = new ArrayList<>();
drawing_action_list = stringToList(Settings.getCorrectionPath(getApplicationContext()));
disableScroll();
if (drawing_action_list.isEmpty())
{
Log.d(TAG,"Drawing action list empty previous path not drawn");
}
else
{
drawing.setPrevious_action_list(drawing_action_list);
Log.d(TAG,"Drawing action list previous path drawn on canvas");
}
}
日志:
A/libc : Fatal signal 11 (SIGSEGV) at 0xb7bdb5a0 (code=1), thread 2064 (hourglass.drawing)
墓碑:
backtrace:
--------- log /dev/log/main
08-20 02:39:00.584 2064 2064 D dalvikvm: Not late-enabling CheckJNI (already on)
08-20 02:39:00.664 2064 2064 W dalvikvm: VFY: unable to find class referenced in signature (Landroid/view/SearchEvent;)
08-20 02:39:00.664 2064 2064 I dalvikvm: Could not find method android.view.Window$Callback.onSearchRequested, referenced from method android.support.v7.view.WindowCallbackWrapper.onSearchRequested
08-20 02:39:00.664 2064 2064 W dalvikvm: VFY: unable to resolve interface method 19785: Landroid/view/Window$Callback;.onSearchRequested (Landroid/view/SearchEvent;)Z
08-20 02:39:00.664 2064 2064 D dalvikvm: VFY: replacing opcode 0x72 at 0x0002
08-20 02:39:00.664 2064 2064 I dalvikvm: Could not find method android.view.Window$Callback.onWindowStartingActionMode, referenced from method android.support.v7.view.WindowCallbackWrapper.onWindowStartingActionMode
08-20 02:39:00.664 2064 2064 W dalvikvm: VFY: unable to resolve interface method 19789: Landroid/view/Window$Callback;.onWindowStartingActionMode (Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
08-20 02:39:00.664 2064 2064 D dalvikvm: VFY: replacing opcode 0x72 at 0x0002
08-20 02:39:00.684 2064 2064 I dalvikvm: Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.widget.TintTypedArray.getChangingConfigurations
08-20 02:39:00.684 2064 2064 W dalvikvm: VFY: unable to resolve virtual method 448: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
08-20 02:39:00.684 2064 2064 D dalvikvm: VFY: replacing opcode 0x6e at 0x0002
08-20 02:39:00.684 2064 2064 I dalvikvm: Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.widget.TintTypedArray.getType
08-20 02:39:00.694 2064 2064 W dalvikvm: VFY: unable to resolve virtual method 470: Landroid/content/res/TypedArray;.getType (I)I
08-20 02:39:00.694 2064 2064 D dalvikvm: VFY: replacing opcode 0x6e at 0x0002
08-20 02:39:00.734 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 240K, 9% free 3098K/3400K, paused 39ms, total 41ms
08-20 02:39:00.884 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 9K, 9% free 3121K/3400K, paused 3ms, total 3ms
08-20 02:39:00.934 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 65.356MB for 65280012-byte allocation
08-20 02:39:00.954 2064 2072 D dalvikvm: GC_FOR_ALLOC freed <1K, 1% free 66870K/67152K, paused 16ms, total 16ms
08-20 02:39:01.254 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 46K, 1% free 66909K/67164K, paused 4ms, total 5ms
08-20 02:39:01.264 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 75.718MB for 10825612-byte allocation
08-20 02:39:01.284 2064 2072 D dalvikvm: GC_FOR_ALLOC freed 2K, 1% free 77479K/77736K, paused 17ms, total 17ms
08-20 02:39:01.314 2064 2064 Din.co.hourglass.drawing.MainActivity: Original pixels3400/796
08-20 02:39:01.324 2064 2064 Din.co.hourglass.drawing.MainActivity: Scaled pixels1700/398
08-20 02:39:01.324 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 1K, 1% free 77478K/77736K, paused 3ms, total 3ms
08-20 02:39:01.324 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 78.296MB for 2706412-byte allocation
08-20 02:39:01.344 2064 2072 D dalvikvm: GC_FOR_ALLOC freed <1K, 1% free 80121K/80380K, paused 15ms, total 15ms
08-20 02:39:01.374 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 10572K, 14% free 69550K/80380K, paused 3ms, total 3ms
08-20 02:39:01.374 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 78.738MB for 11288012-byte allocation
08-20 02:39:01.424 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 12% free 80573K/91404K, paused 2ms, total 2ms
08-20 02:39:01.424 2064 2064 Din.co.hourglass.drawing.MainActivity: Original pixels3400/830
08-20 02:39:01.424 2064 2064 Din.co.hourglass.drawing.MainActivity: Scaled pixels1700/415
08-20 02:39:01.424 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 12% free 80573K/91404K, paused 3ms, total 3ms
08-20 02:39:01.434 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 81.429MB for 2822012-byte allocation
08-20 02:39:01.434 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 9% free 83329K/91404K, paused 3ms, total 3ms
08-20 02:39:01.434 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 9% free 83329K/91404K, paused 2ms, total 3ms
08-20 02:39:01.434 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 86.701MB for 5528412-byte allocation
08-20 02:39:01.444 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 3% free 88728K/91404K, paused 2ms, total 2ms
08-20 02:39:01.484 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 16422K, 4% free 72306K/75312K, paused 4ms, total 4ms
08-20 02:39:01.484 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 81.221MB for 11070412-byte allocation
08-20 02:39:01.534 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 4% free 83117K/86124K, paused 10ms, total 10ms
08-20 02:39:01.534 2064 2064 Din.co.hourglass.drawing.MainActivity: Original pixels3400/814
08-20 02:39:01.534 2064 2064 Din.co.hourglass.drawing.MainActivity: Scaled pixels1700/407
08-20 02:39:01.544 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 4% free 83117K/86124K, paused 8ms, total 8ms
08-20 02:39:01.544 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 83.861MB for 2767612-byte allocation
08-20 02:39:01.554 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 1% free 85819K/86124K, paused 12ms, total 12ms
08-20 02:39:01.564 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 10811K, 1% free 75008K/75312K, paused 2ms, total 3ms
08-20 02:39:01.564 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 81.215MB for 8296012-byte allocation
08-20 02:39:01.574 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 1% free 83110K/83416K, paused 5ms, total 6ms
08-20 02:39:01.594 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 8101K, 11% free 75009K/83416K, paused 4ms, total 4ms
08-20 02:39:01.594 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 77.350MB for 4243212-byte allocation
08-20 02:39:01.614 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 6% free 79152K/83416K, paused 2ms, total 2ms
08-20 02:39:01.614 2064 2064 Din.co.hourglass.drawing.MainActivity: Original pixels3400/312
08-20 02:39:01.614 2064 2064 Din.co.hourglass.drawing.MainActivity: Scaled pixels1700/156
08-20 02:39:01.614 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 4144K, 9% free 76045K/83416K, paused 2ms, total 3ms
08-20 02:39:01.614 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 83.239MB for 9356812-byte allocation
08-20 02:39:01.624 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 8% free 85182K/92556K, paused 2ms, total 3ms
08-20 02:39:01.624 2064 2064 Din.co.hourglass.drawing.MainActivity: Bitmap Merged
08-20 02:39:01.714 2064 2064 D : HostConnection::get() New Host Connection established 0xb833f3c0, tid 2064
08-20 02:39:02.844 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 18381K, 8% free 67150K/72492K, paused 3ms, total 8ms
08-20 02:39:02.844 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 77.371MB for 12312340-byte allocation
08-20 02:39:02.884 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 8K, 7% free 79165K/84516K, paused 3ms, total 3ms
08-20 02:39:02.904 2064 2064 D lingaraj: adding canvas index from previous list0
08-20 02:39:02.904 2064 2064 D lingaraj: history pointer update0
08-20 02:39:02.904 2064 2064 D lingaraj: adding canvas index from previous list1
08-20 02:39:02.904 2064 2064 D lingaraj: history pointer update1
08-20 02:39:02.914 2064 2064 D Drawing: Drawing action list previous path drawn on canvas
08-20 02:39:03.074 2064 2064 D dalvikvm: GC_FOR_ALLOC freed 337K, 7% free 79264K/84516K, paused 3ms, total 4ms
08-20 02:39:03.074 2064 2064 I dalvikvm-heap: Grow heap (frag case) to 86.820MB for 9815116-byte allocation
08-20 02:39:03.084 2064 2064 D dalvikvm: GC_FOR_ALLOC freed <1K, 6% free 88849K/94104K, paused 2ms, total 3ms
08-20 02:39:03.084 2064 2064 F libc : Fatal signal 11 (SIGSEGV) at 0xb7bdb5a0 (code=1), thread 2064 (hourglass.drawing)
最佳答案
转换和保存对象(如油漆等)时出现问题。 对于您想实现的目标,我有一个替代解决方案:- 您希望优先保存以下数据列表:-
private DrawingView.Type type;
private Path path;
private Paint paint;
private String text;
private DrawingView.Stamper stamper;
private float positionX;
private float positionY;
取而代之的是,您可以使用原始数据并实现 parcelable。我的意思是你不需要写整个 paint 对象,而是你在 paint 对象中设置的值,即一些原始值。 (类似地检查压模和类型)
关于android - 将 Canvas 路径保存到 SharedPreference 并在重新打开应用程序时在 Canvas 上重绘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39051344/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
如何使此根路径转到:“/dashboard”而不仅仅是http://example.com?root:to=>'dashboard#index',:constraints=>lambda{|req|!req.session[:user_id].blank?} 最佳答案 您可以通过以下方式实现:root:to=>redirect('/dashboard')match'/dashboard',:to=>"dashboard#index",:constraints=>lambda{|req|!req.session[:user_id].b
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
当我创建一个Rails应用程序时,控制台:railsnewfoo我的代码可以使用字符串“foo”吗?puts"Yourapp'snameis"+app_name_bar 最佳答案 Rails.application.class将为您提供应用程序的全名(例如YourAppName::Application)。从那里您可以使用Rails.application.class.parent获取模块名称。 关于ruby-on-rails-应用程序的名称是否可以作为变量使用?,我们在StackOve